1 /*
2 ************************************************************************************************************************
3 *
4 * Copyright (C) 2007-2022 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::ComputeSurfaceCoordFromAddr
388 *
389 * @brief
390 * Interface function stub of ComputeSurfaceCoordFromAddr.
391 *
392 * @return
393 * ADDR_E_RETURNCODE
394 ************************************************************************************************************************
395 */
ComputeSurfaceCoordFromAddr(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const396 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddr(
397 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
398 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
399 ) const
400 {
401 ADDR_E_RETURNCODE returnCode = ADDR_OK;
402
403 if (GetFillSizeFieldsFlags() == TRUE)
404 {
405 if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) ||
406 (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT)))
407 {
408 returnCode = ADDR_PARAMSIZEMISMATCH;
409 }
410 }
411
412 if ((pIn->bpp < 8) ||
413 (pIn->bpp > 128) ||
414 ((pIn->bpp % 8) != 0) ||
415 (pIn->bitPosition >= 8))
416 {
417 returnCode = ADDR_INVALIDPARAMS;
418 }
419
420 if (returnCode == ADDR_OK)
421 {
422 if (IsLinear(pIn->swizzleMode))
423 {
424 returnCode = ComputeSurfaceCoordFromAddrLinear(pIn, pOut);
425 }
426 else
427 {
428 returnCode = ComputeSurfaceCoordFromAddrTiled(pIn, pOut);
429 }
430 }
431
432 return returnCode;
433 }
434
435
436 ////////////////////////////////////////////////////////////////////////////////////////////////////
437 // CMASK/HTILE
438 ////////////////////////////////////////////////////////////////////////////////////////////////////
439
440 /**
441 ************************************************************************************************************************
442 * Lib::ComputeHtileInfo
443 *
444 * @brief
445 * Interface function stub of AddrComputeHtilenfo
446 *
447 * @return
448 * ADDR_E_RETURNCODE
449 ************************************************************************************************************************
450 */
ComputeHtileInfo(const ADDR2_COMPUTE_HTILE_INFO_INPUT * pIn,ADDR2_COMPUTE_HTILE_INFO_OUTPUT * pOut) const451 ADDR_E_RETURNCODE Lib::ComputeHtileInfo(
452 const ADDR2_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] input structure
453 ADDR2_COMPUTE_HTILE_INFO_OUTPUT* pOut ///< [out] output structure
454 ) const
455 {
456 ADDR_E_RETURNCODE returnCode;
457
458 if ((GetFillSizeFieldsFlags() == TRUE) &&
459 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT)) ||
460 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT))))
461 {
462 returnCode = ADDR_INVALIDPARAMS;
463 }
464 else
465 {
466 returnCode = HwlComputeHtileInfo(pIn, pOut);
467
468 ValidMetaBaseAlignments(pOut->baseAlign);
469 }
470
471 return returnCode;
472 }
473
474 /**
475 ************************************************************************************************************************
476 * Lib::ComputeHtileAddrFromCoord
477 *
478 * @brief
479 * Interface function stub of AddrComputeHtileAddrFromCoord
480 *
481 * @return
482 * ADDR_E_RETURNCODE
483 ************************************************************************************************************************
484 */
ComputeHtileAddrFromCoord(const ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT * pOut)485 ADDR_E_RETURNCODE Lib::ComputeHtileAddrFromCoord(
486 const ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
487 ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] output structure
488 {
489 ADDR_E_RETURNCODE returnCode;
490
491 if ((GetFillSizeFieldsFlags() == TRUE) &&
492 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) ||
493 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT))))
494 {
495 returnCode = ADDR_INVALIDPARAMS;
496 }
497 else
498 {
499 returnCode = HwlComputeHtileAddrFromCoord(pIn, pOut);
500 }
501
502 return returnCode;
503 }
504
505 /**
506 ************************************************************************************************************************
507 * Lib::ComputeHtileCoordFromAddr
508 *
509 * @brief
510 * Interface function stub of AddrComputeHtileCoordFromAddr
511 *
512 * @return
513 * ADDR_E_RETURNCODE
514 ************************************************************************************************************************
515 */
ComputeHtileCoordFromAddr(const ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT * pOut)516 ADDR_E_RETURNCODE Lib::ComputeHtileCoordFromAddr(
517 const ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
518 ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut) ///< [out] output structure
519 {
520 ADDR_E_RETURNCODE returnCode;
521
522 if ((GetFillSizeFieldsFlags() == TRUE) &&
523 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT)) ||
524 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT))))
525 {
526 returnCode = ADDR_INVALIDPARAMS;
527 }
528 else
529 {
530 returnCode = HwlComputeHtileCoordFromAddr(pIn, pOut);
531 }
532
533 return returnCode;
534 }
535
536 /**
537 ************************************************************************************************************************
538 * Lib::ComputeCmaskInfo
539 *
540 * @brief
541 * Interface function stub of AddrComputeCmaskInfo
542 *
543 * @return
544 * ADDR_E_RETURNCODE
545 ************************************************************************************************************************
546 */
ComputeCmaskInfo(const ADDR2_COMPUTE_CMASK_INFO_INPUT * pIn,ADDR2_COMPUTE_CMASK_INFO_OUTPUT * pOut) const547 ADDR_E_RETURNCODE Lib::ComputeCmaskInfo(
548 const ADDR2_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] input structure
549 ADDR2_COMPUTE_CMASK_INFO_OUTPUT* pOut ///< [out] output structure
550 ) const
551 {
552 ADDR_E_RETURNCODE returnCode;
553
554 if ((GetFillSizeFieldsFlags() == TRUE) &&
555 ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT)) ||
556 (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT))))
557 {
558 returnCode = ADDR_INVALIDPARAMS;
559 }
560 else if (pIn->cMaskFlags.linear)
561 {
562 returnCode = ADDR_INVALIDPARAMS;
563 }
564 else
565 {
566 returnCode = HwlComputeCmaskInfo(pIn, pOut);
567
568 ValidMetaBaseAlignments(pOut->baseAlign);
569 }
570
571 return returnCode;
572 }
573
574 /**
575 ************************************************************************************************************************
576 * Lib::ComputeCmaskAddrFromCoord
577 *
578 * @brief
579 * Interface function stub of AddrComputeCmaskAddrFromCoord
580 *
581 * @return
582 * ADDR_E_RETURNCODE
583 ************************************************************************************************************************
584 */
ComputeCmaskAddrFromCoord(const ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT * pOut)585 ADDR_E_RETURNCODE Lib::ComputeCmaskAddrFromCoord(
586 const ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
587 ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] output structure
588 {
589 ADDR_E_RETURNCODE returnCode;
590
591 if ((GetFillSizeFieldsFlags() == TRUE) &&
592 ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) ||
593 (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT))))
594 {
595 returnCode = ADDR_INVALIDPARAMS;
596 }
597 else
598 {
599 returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut);
600 }
601
602 return returnCode;
603 }
604
605 /**
606 ************************************************************************************************************************
607 * Lib::ComputeCmaskCoordFromAddr
608 *
609 * @brief
610 * Interface function stub of AddrComputeCmaskCoordFromAddr
611 *
612 * @return
613 * ADDR_E_RETURNCODE
614 ************************************************************************************************************************
615 */
ComputeCmaskCoordFromAddr(const ADDR2_COMPUTE_CMASK_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_CMASK_COORDFROMADDR_OUTPUT * pOut) const616 ADDR_E_RETURNCODE Lib::ComputeCmaskCoordFromAddr(
617 const ADDR2_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
618 ADDR2_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
619 ) const
620 {
621 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
622
623 ADDR_NOT_IMPLEMENTED();
624
625 return returnCode;
626 }
627
628 /**
629 ************************************************************************************************************************
630 * Lib::ComputeFmaskInfo
631 *
632 * @brief
633 * Interface function stub of ComputeFmaskInfo.
634 *
635 * @return
636 * ADDR_E_RETURNCODE
637 ************************************************************************************************************************
638 */
ComputeFmaskInfo(const ADDR2_COMPUTE_FMASK_INFO_INPUT * pIn,ADDR2_COMPUTE_FMASK_INFO_OUTPUT * pOut)639 ADDR_E_RETURNCODE Lib::ComputeFmaskInfo(
640 const ADDR2_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
641 ADDR2_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
642 )
643 {
644 ADDR_E_RETURNCODE returnCode;
645
646 BOOL_32 valid = (IsZOrderSwizzle(pIn->swizzleMode) == TRUE) &&
647 ((pIn->numSamples > 0) || (pIn->numFrags > 0));
648
649 if (GetFillSizeFieldsFlags())
650 {
651 if ((pIn->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT)) ||
652 (pOut->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT)))
653 {
654 valid = FALSE;
655 }
656 }
657
658 if (valid == FALSE)
659 {
660 returnCode = ADDR_INVALIDPARAMS;
661 }
662 else
663 {
664 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
665 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
666
667 localIn.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT);
668 localOut.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT);
669
670 localIn.swizzleMode = pIn->swizzleMode;
671 localIn.numSlices = Max(pIn->numSlices, 1u);
672 localIn.width = Max(pIn->unalignedWidth, 1u);
673 localIn.height = Max(pIn->unalignedHeight, 1u);
674 localIn.bpp = GetFmaskBpp(pIn->numSamples, pIn->numFrags);
675 localIn.flags.fmask = 1;
676 localIn.numFrags = 1;
677 localIn.numSamples = 1;
678 localIn.resourceType = ADDR_RSRC_TEX_2D;
679
680 if (localIn.bpp == 8)
681 {
682 localIn.format = ADDR_FMT_8;
683 }
684 else if (localIn.bpp == 16)
685 {
686 localIn.format = ADDR_FMT_16;
687 }
688 else if (localIn.bpp == 32)
689 {
690 localIn.format = ADDR_FMT_32;
691 }
692 else
693 {
694 localIn.format = ADDR_FMT_32_32;
695 }
696
697 returnCode = ComputeSurfaceInfo(&localIn, &localOut);
698
699 if (returnCode == ADDR_OK)
700 {
701 pOut->pitch = localOut.pitch;
702 pOut->height = localOut.height;
703 pOut->baseAlign = localOut.baseAlign;
704 pOut->numSlices = localOut.numSlices;
705 pOut->fmaskBytes = static_cast<UINT_32>(localOut.surfSize);
706 pOut->sliceSize = static_cast<UINT_32>(localOut.sliceSize);
707 pOut->bpp = localIn.bpp;
708 pOut->numSamples = 1;
709 }
710 }
711
712 ValidBaseAlignments(pOut->baseAlign);
713
714 return returnCode;
715 }
716
717 /**
718 ************************************************************************************************************************
719 * Lib::ComputeFmaskAddrFromCoord
720 *
721 * @brief
722 * Interface function stub of ComputeFmaskAddrFromCoord.
723 *
724 * @return
725 * ADDR_E_RETURNCODE
726 ************************************************************************************************************************
727 */
ComputeFmaskAddrFromCoord(const ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT * pOut) const728 ADDR_E_RETURNCODE Lib::ComputeFmaskAddrFromCoord(
729 const ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
730 ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
731 ) const
732 {
733 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
734
735 ADDR_NOT_IMPLEMENTED();
736
737 return returnCode;
738 }
739
740 /**
741 ************************************************************************************************************************
742 * Lib::ComputeFmaskCoordFromAddr
743 *
744 * @brief
745 * Interface function stub of ComputeFmaskAddrFromCoord.
746 *
747 * @return
748 * ADDR_E_RETURNCODE
749 ************************************************************************************************************************
750 */
ComputeFmaskCoordFromAddr(const ADDR2_COMPUTE_FMASK_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_FMASK_COORDFROMADDR_OUTPUT * pOut) const751 ADDR_E_RETURNCODE Lib::ComputeFmaskCoordFromAddr(
752 const ADDR2_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
753 ADDR2_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
754 ) const
755 {
756 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
757
758 ADDR_NOT_IMPLEMENTED();
759
760 return returnCode;
761 }
762
763 /**
764 ************************************************************************************************************************
765 * Lib::ComputeDccInfo
766 *
767 * @brief
768 * Interface function to compute DCC key info
769 *
770 * @return
771 * return code of HwlComputeDccInfo
772 ************************************************************************************************************************
773 */
ComputeDccInfo(const ADDR2_COMPUTE_DCCINFO_INPUT * pIn,ADDR2_COMPUTE_DCCINFO_OUTPUT * pOut) const774 ADDR_E_RETURNCODE Lib::ComputeDccInfo(
775 const ADDR2_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input structure
776 ADDR2_COMPUTE_DCCINFO_OUTPUT* pOut ///< [out] output structure
777 ) const
778 {
779 ADDR_E_RETURNCODE returnCode;
780
781 if ((GetFillSizeFieldsFlags() == TRUE) &&
782 ((pIn->size != sizeof(ADDR2_COMPUTE_DCCINFO_INPUT)) ||
783 (pOut->size != sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT))))
784 {
785 returnCode = ADDR_INVALIDPARAMS;
786 }
787 else
788 {
789 returnCode = HwlComputeDccInfo(pIn, pOut);
790
791 ValidMetaBaseAlignments(pOut->dccRamBaseAlign);
792 }
793
794 return returnCode;
795 }
796
797 /**
798 ************************************************************************************************************************
799 * Lib::ComputeDccAddrFromCoord
800 *
801 * @brief
802 * Interface function stub of ComputeDccAddrFromCoord
803 *
804 * @return
805 * ADDR_E_RETURNCODE
806 ************************************************************************************************************************
807 */
ComputeDccAddrFromCoord(const ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT * pOut)808 ADDR_E_RETURNCODE Lib::ComputeDccAddrFromCoord(
809 const ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
810 ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT* pOut) ///< [out] output structure
811 {
812 ADDR_E_RETURNCODE returnCode;
813
814 if ((GetFillSizeFieldsFlags() == TRUE) &&
815 ((pIn->size != sizeof(ADDR2_COMPUTE_DCC_ADDRFROMCOORD_INPUT)) ||
816 (pOut->size != sizeof(ADDR2_COMPUTE_DCC_ADDRFROMCOORD_OUTPUT))))
817 {
818 returnCode = ADDR_INVALIDPARAMS;
819 }
820 else
821 {
822 returnCode = HwlSupportComputeDccAddrFromCoord(pIn);
823
824 if (returnCode == ADDR_OK)
825 {
826 HwlComputeDccAddrFromCoord(pIn, pOut);
827 }
828 }
829
830 return returnCode;
831 }
832
833 /**
834 ************************************************************************************************************************
835 * Lib::ComputePipeBankXor
836 *
837 * @brief
838 * Interface function stub of Addr2ComputePipeBankXor.
839 *
840 * @return
841 * ADDR_E_RETURNCODE
842 ************************************************************************************************************************
843 */
ComputePipeBankXor(const ADDR2_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)844 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
845 const ADDR2_COMPUTE_PIPEBANKXOR_INPUT* pIn,
846 ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT* pOut)
847 {
848 ADDR_E_RETURNCODE returnCode;
849
850 if ((GetFillSizeFieldsFlags() == TRUE) &&
851 ((pIn->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT)) ||
852 (pOut->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT))))
853 {
854 returnCode = ADDR_INVALIDPARAMS;
855 }
856 else
857 {
858 returnCode = HwlComputePipeBankXor(pIn, pOut);
859 }
860
861 return returnCode;
862 }
863
864 /**
865 ************************************************************************************************************************
866 * Lib::ComputeSlicePipeBankXor
867 *
868 * @brief
869 * Interface function stub of Addr2ComputeSlicePipeBankXor.
870 *
871 * @return
872 * ADDR_E_RETURNCODE
873 ************************************************************************************************************************
874 */
ComputeSlicePipeBankXor(const ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)875 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
876 const ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
877 ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut)
878 {
879 ADDR_E_RETURNCODE returnCode;
880
881 if ((GetFillSizeFieldsFlags() == TRUE) &&
882 ((pIn->size != sizeof(ADDR2_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
883 (pOut->size != sizeof(ADDR2_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
884 {
885 returnCode = ADDR_INVALIDPARAMS;
886 }
887 else if ((IsThin(pIn->resourceType, pIn->swizzleMode) == FALSE) ||
888 (IsNonPrtXor(pIn->swizzleMode) == FALSE) ||
889 (pIn->numSamples > 1))
890 {
891 returnCode = ADDR_NOTSUPPORTED;
892 }
893 else if ((pIn->bpe != 0) &&
894 (pIn->bpe != 8) &&
895 (pIn->bpe != 16) &&
896 (pIn->bpe != 32) &&
897 (pIn->bpe != 64) &&
898 (pIn->bpe != 128))
899 {
900 returnCode = ADDR_INVALIDPARAMS;
901 }
902 else
903 {
904 returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
905 }
906
907 return returnCode;
908 }
909
910 /**
911 ************************************************************************************************************************
912 * Lib::ComputeSubResourceOffsetForSwizzlePattern
913 *
914 * @brief
915 * Interface function stub of Addr2ComputeSubResourceOffsetForSwizzlePattern.
916 *
917 * @return
918 * ADDR_E_RETURNCODE
919 ************************************************************************************************************************
920 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)921 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
922 const ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
923 ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut)
924 {
925 ADDR_E_RETURNCODE returnCode;
926
927 if ((GetFillSizeFieldsFlags() == TRUE) &&
928 ((pIn->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
929 (pOut->size != sizeof(ADDR2_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
930 {
931 returnCode = ADDR_INVALIDPARAMS;
932 }
933 else
934 {
935 returnCode = HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
936 }
937
938 return returnCode;
939 }
940
941 /**
942 ************************************************************************************************************************
943 * Lib::ComputeNonBlockCompressedView
944 *
945 * @brief
946 * Interface function stub of Addr2ComputeNonBlockCompressedView.
947 *
948 * @return
949 * ADDR_E_RETURNCODE
950 ************************************************************************************************************************
951 */
ComputeNonBlockCompressedView(const ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)952 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
953 const ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
954 ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut)
955 {
956 ADDR_E_RETURNCODE returnCode;
957
958 if ((GetFillSizeFieldsFlags() == TRUE) &&
959 ((pIn->size != sizeof(ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
960 (pOut->size != sizeof(ADDR2_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
961 {
962 returnCode = ADDR_INVALIDPARAMS;
963 }
964 else
965 {
966 returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
967 }
968
969 return returnCode;
970 }
971
972 /**
973 ************************************************************************************************************************
974 * Lib::ExtractPipeBankXor
975 *
976 * @brief
977 * Internal function to extract bank and pipe xor bits from combined xor bits.
978 *
979 * @return
980 * ADDR_E_RETURNCODE
981 ************************************************************************************************************************
982 */
ExtractPipeBankXor(UINT_32 pipeBankXor,UINT_32 bankBits,UINT_32 pipeBits,UINT_32 * pBankX,UINT_32 * pPipeX)983 ADDR_E_RETURNCODE Lib::ExtractPipeBankXor(
984 UINT_32 pipeBankXor,
985 UINT_32 bankBits,
986 UINT_32 pipeBits,
987 UINT_32* pBankX,
988 UINT_32* pPipeX)
989 {
990 ADDR_E_RETURNCODE returnCode;
991
992 if (pipeBankXor < (1u << (pipeBits + bankBits)))
993 {
994 *pPipeX = pipeBankXor % (1 << pipeBits);
995 *pBankX = pipeBankXor >> pipeBits;
996 returnCode = ADDR_OK;
997 }
998 else
999 {
1000 ADDR_ASSERT_ALWAYS();
1001 returnCode = ADDR_INVALIDPARAMS;
1002 }
1003
1004 return returnCode;
1005 }
1006
1007 /**
1008 ************************************************************************************************************************
1009 * Lib::ComputeSurfaceInfoSanityCheck
1010 *
1011 * @brief
1012 * Internal function to do basic sanity check before compute surface info
1013 *
1014 * @return
1015 * ADDR_E_RETURNCODE
1016 ************************************************************************************************************************
1017 */
ComputeSurfaceInfoSanityCheck(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn) const1018 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoSanityCheck(
1019 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in] input structure
1020 ) const
1021 {
1022 ADDR_E_RETURNCODE returnCode;
1023
1024 if ((GetFillSizeFieldsFlags() == TRUE) &&
1025 (pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT)))
1026 {
1027 returnCode = ADDR_INVALIDPARAMS;
1028 }
1029 else
1030 {
1031 returnCode = HwlComputeSurfaceInfoSanityCheck(pIn);
1032 }
1033
1034 return returnCode;
1035 }
1036
1037 /**
1038 ************************************************************************************************************************
1039 * Lib::ApplyCustomizedPitchHeight
1040 *
1041 * @brief
1042 * Helper function to override hw required row pitch/slice pitch by customrized one
1043 *
1044 * @return
1045 * ADDR_E_RETURNCODE
1046 ************************************************************************************************************************
1047 */
ApplyCustomizedPitchHeight(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,UINT_32 elementBytes,UINT_32 pitchAlignInElement,UINT_32 * pPitch,UINT_32 * pHeight) const1048 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
1049 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1050 UINT_32 elementBytes, ///< [in] element bytes per element
1051 UINT_32 pitchAlignInElement, ///< [in] pitch alignment in element
1052 UINT_32* pPitch, ///< [in/out] pitch
1053 UINT_32* pHeight ///< [in/out] height
1054 ) const
1055 {
1056 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1057
1058 if (pIn->numMipLevels <= 1)
1059 {
1060 if (pIn->pitchInElement > 0)
1061 {
1062 if ((pIn->pitchInElement % pitchAlignInElement) != 0)
1063 {
1064 returnCode = ADDR_INVALIDPARAMS;
1065 }
1066 else if (pIn->pitchInElement < (*pPitch))
1067 {
1068 returnCode = ADDR_INVALIDPARAMS;
1069 }
1070 else
1071 {
1072 *pPitch = pIn->pitchInElement;
1073 }
1074 }
1075
1076 if (returnCode == ADDR_OK)
1077 {
1078 if (pIn->sliceAlign > 0)
1079 {
1080 UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / (*pPitch);
1081
1082 if (customizedHeight * elementBytes * (*pPitch) != pIn->sliceAlign)
1083 {
1084 returnCode = ADDR_INVALIDPARAMS;
1085 }
1086 else if ((pIn->numSlices > 1) && ((*pHeight) != customizedHeight))
1087 {
1088 returnCode = ADDR_INVALIDPARAMS;
1089 }
1090 else
1091 {
1092 *pHeight = customizedHeight;
1093 }
1094 }
1095 }
1096 }
1097
1098 return returnCode;
1099 }
1100
1101 /**
1102 ************************************************************************************************************************
1103 * Lib::ComputeSurfaceInfoLinear
1104 *
1105 * @brief
1106 * Internal function to calculate alignment for linear swizzle surface
1107 *
1108 * @return
1109 * ADDR_E_RETURNCODE
1110 ************************************************************************************************************************
1111 */
ComputeSurfaceInfoLinear(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1112 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoLinear(
1113 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1114 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
1115 ) const
1116 {
1117 return HwlComputeSurfaceInfoLinear(pIn, pOut);
1118 }
1119
1120 /**
1121 ************************************************************************************************************************
1122 * Lib::ComputeSurfaceInfoTiled
1123 *
1124 * @brief
1125 * Internal function to calculate alignment for tiled swizzle surface
1126 *
1127 * @return
1128 * ADDR_E_RETURNCODE
1129 ************************************************************************************************************************
1130 */
ComputeSurfaceInfoTiled(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1131 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoTiled(
1132 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1133 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
1134 ) const
1135 {
1136 return HwlComputeSurfaceInfoTiled(pIn, pOut);
1137 }
1138
1139 /**
1140 ************************************************************************************************************************
1141 * Lib::ComputeSurfaceAddrFromCoordLinear
1142 *
1143 * @brief
1144 * Internal function to calculate address from coord for linear swizzle surface
1145 *
1146 * @return
1147 * ADDR_E_RETURNCODE
1148 ************************************************************************************************************************
1149 */
ComputeSurfaceAddrFromCoordLinear(const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const1150 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
1151 const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
1152 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
1153 ) const
1154 {
1155 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1156 BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1) && (pIn->pipeBankXor == 0);
1157
1158 if (valid)
1159 {
1160 if (IsTex1d(pIn->resourceType))
1161 {
1162 valid = (pIn->y == 0);
1163 }
1164 }
1165
1166 if (valid)
1167 {
1168 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
1169 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1170 ADDR2_MIP_INFO mipInfo[MaxMipLevels];
1171 ADDR_ASSERT(pIn->numMipLevels <= MaxMipLevels);
1172
1173 localIn.bpp = pIn->bpp;
1174 localIn.swizzleMode = pIn->swizzleMode;
1175 localIn.flags = pIn->flags;
1176 localIn.width = Max(pIn->unalignedWidth, 1u);
1177 localIn.height = Max(pIn->unalignedHeight, 1u);
1178 localIn.numSlices = Max(pIn->numSlices, 1u);
1179 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1180 localIn.resourceType = pIn->resourceType;
1181
1182 if (localIn.numMipLevels <= 1)
1183 {
1184 localIn.pitchInElement = pIn->pitchInElement;
1185 }
1186
1187 localOut.pMipInfo = mipInfo;
1188
1189 returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1190
1191 if (returnCode == ADDR_OK)
1192 {
1193 pOut->addr = (localOut.sliceSize * pIn->slice) +
1194 mipInfo[pIn->mipId].offset +
1195 (pIn->y * mipInfo[pIn->mipId].pitch + pIn->x) * (pIn->bpp >> 3);
1196 pOut->bitPosition = 0;
1197 }
1198 else
1199 {
1200 valid = FALSE;
1201 }
1202 }
1203
1204 if (valid == FALSE)
1205 {
1206 returnCode = ADDR_INVALIDPARAMS;
1207 }
1208
1209 return returnCode;
1210 }
1211
1212 /**
1213 ************************************************************************************************************************
1214 * Lib::ComputeSurfaceAddrFromCoordTiled
1215 *
1216 * @brief
1217 * Internal function to calculate address from coord for tiled swizzle surface
1218 *
1219 * @return
1220 * ADDR_E_RETURNCODE
1221 ************************************************************************************************************************
1222 */
ComputeSurfaceAddrFromCoordTiled(const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const1223 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
1224 const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
1225 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
1226 ) const
1227 {
1228 return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
1229 }
1230
1231 /**
1232 ************************************************************************************************************************
1233 * Lib::ComputeSurfaceCoordFromAddrLinear
1234 *
1235 * @brief
1236 * Internal function to calculate coord from address for linear swizzle surface
1237 *
1238 * @return
1239 * ADDR_E_RETURNCODE
1240 ************************************************************************************************************************
1241 */
ComputeSurfaceCoordFromAddrLinear(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const1242 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrLinear(
1243 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
1244 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
1245 ) const
1246 {
1247 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1248
1249 BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1);
1250
1251 if (valid)
1252 {
1253 if (IsTex1d(pIn->resourceType))
1254 {
1255 valid = (pIn->unalignedHeight == 1);
1256 }
1257 }
1258
1259 if (valid)
1260 {
1261 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
1262 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1263 localIn.bpp = pIn->bpp;
1264 localIn.swizzleMode = pIn->swizzleMode;
1265 localIn.flags = pIn->flags;
1266 localIn.width = Max(pIn->unalignedWidth, 1u);
1267 localIn.height = Max(pIn->unalignedHeight, 1u);
1268 localIn.numSlices = Max(pIn->numSlices, 1u);
1269 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1270 localIn.resourceType = pIn->resourceType;
1271 if (localIn.numMipLevels <= 1)
1272 {
1273 localIn.pitchInElement = pIn->pitchInElement;
1274 }
1275 returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1276
1277 if (returnCode == ADDR_OK)
1278 {
1279 pOut->slice = static_cast<UINT_32>(pIn->addr / localOut.sliceSize);
1280 pOut->sample = 0;
1281
1282 UINT_32 offsetInSlice = static_cast<UINT_32>(pIn->addr % localOut.sliceSize);
1283 UINT_32 elementBytes = pIn->bpp >> 3;
1284 UINT_32 mipOffsetInSlice = 0;
1285 UINT_32 mipSize = 0;
1286 UINT_32 mipId = 0;
1287 for (; mipId < pIn->numMipLevels ; mipId++)
1288 {
1289 if (IsTex1d(pIn->resourceType))
1290 {
1291 mipSize = localOut.pitch * elementBytes;
1292 }
1293 else
1294 {
1295 UINT_32 currentMipHeight = (PowTwoAlign(localIn.height, (1 << mipId))) >> mipId;
1296 mipSize = currentMipHeight * localOut.pitch * elementBytes;
1297 }
1298
1299 if (mipSize == 0)
1300 {
1301 valid = FALSE;
1302 break;
1303 }
1304 else if ((mipSize + mipOffsetInSlice) > offsetInSlice)
1305 {
1306 break;
1307 }
1308 else
1309 {
1310 mipOffsetInSlice += mipSize;
1311 if ((mipId == (pIn->numMipLevels - 1)) ||
1312 (mipOffsetInSlice >= localOut.sliceSize))
1313 {
1314 valid = FALSE;
1315 }
1316 }
1317 }
1318
1319 if (valid)
1320 {
1321 pOut->mipId = mipId;
1322
1323 UINT_32 elemOffsetInMip = (offsetInSlice - mipOffsetInSlice) / elementBytes;
1324 if (IsTex1d(pIn->resourceType))
1325 {
1326 if (elemOffsetInMip < localOut.pitch)
1327 {
1328 pOut->x = elemOffsetInMip;
1329 pOut->y = 0;
1330 }
1331 else
1332 {
1333 valid = FALSE;
1334 }
1335 }
1336 else
1337 {
1338 pOut->y = elemOffsetInMip / localOut.pitch;
1339 pOut->x = elemOffsetInMip % localOut.pitch;
1340 }
1341
1342 if ((pOut->slice >= pIn->numSlices) ||
1343 (pOut->mipId >= pIn->numMipLevels) ||
1344 (pOut->x >= Max((pIn->unalignedWidth >> pOut->mipId), 1u)) ||
1345 (pOut->y >= Max((pIn->unalignedHeight >> pOut->mipId), 1u)) ||
1346 (IsTex3d(pIn->resourceType) &&
1347 (FALSE == Valid3DMipSliceIdConstraint(pIn->numSlices,
1348 pOut->mipId,
1349 pOut->slice))))
1350 {
1351 valid = FALSE;
1352 }
1353 }
1354 }
1355 else
1356 {
1357 valid = FALSE;
1358 }
1359 }
1360
1361 if (valid == FALSE)
1362 {
1363 returnCode = ADDR_INVALIDPARAMS;
1364 }
1365
1366 return returnCode;
1367 }
1368
1369 /**
1370 ************************************************************************************************************************
1371 * Lib::ComputeSurfaceCoordFromAddrTiled
1372 *
1373 * @brief
1374 * Internal function to calculate coord from address for tiled swizzle surface
1375 *
1376 * @return
1377 * ADDR_E_RETURNCODE
1378 ************************************************************************************************************************
1379 */
ComputeSurfaceCoordFromAddrTiled(const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT * pIn,ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT * pOut) const1380 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrTiled(
1381 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
1382 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
1383 ) const
1384 {
1385 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
1386
1387 ADDR_NOT_IMPLEMENTED();
1388
1389 return returnCode;
1390 }
1391
1392 /**
1393 ************************************************************************************************************************
1394 * Lib::ComputeBlockDimensionForSurf
1395 *
1396 * @brief
1397 * Internal function to get block width/height/depth in element from surface input params.
1398 *
1399 * @return
1400 * ADDR_E_RETURNCODE
1401 ************************************************************************************************************************
1402 */
ComputeBlockDimensionForSurf(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,UINT_32 numSamples,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1403 ADDR_E_RETURNCODE Lib::ComputeBlockDimensionForSurf(
1404 UINT_32* pWidth,
1405 UINT_32* pHeight,
1406 UINT_32* pDepth,
1407 UINT_32 bpp,
1408 UINT_32 numSamples,
1409 AddrResourceType resourceType,
1410 AddrSwizzleMode swizzleMode) const
1411 {
1412 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1413
1414 if (IsThick(resourceType, swizzleMode))
1415 {
1416 ComputeThickBlockDimension(pWidth, pHeight, pDepth, bpp, resourceType, swizzleMode);
1417 }
1418 else if (IsThin(resourceType, swizzleMode))
1419 {
1420 ComputeThinBlockDimension(pWidth, pHeight, pDepth, bpp, numSamples, resourceType, swizzleMode);
1421 }
1422 else
1423 {
1424 ADDR_ASSERT_ALWAYS();
1425 returnCode = ADDR_INVALIDPARAMS;
1426 }
1427
1428 return returnCode;
1429 }
1430
1431 /**
1432 ************************************************************************************************************************
1433 * Lib::ComputeThinBlockDimension
1434 *
1435 * @brief
1436 * Internal function to get thin block width/height/depth in element from surface input params.
1437 *
1438 * @return
1439 * N/A
1440 ************************************************************************************************************************
1441 */
ComputeThinBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,UINT_32 numSamples,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1442 VOID Lib::ComputeThinBlockDimension(
1443 UINT_32* pWidth,
1444 UINT_32* pHeight,
1445 UINT_32* pDepth,
1446 UINT_32 bpp,
1447 UINT_32 numSamples,
1448 AddrResourceType resourceType,
1449 AddrSwizzleMode swizzleMode) const
1450 {
1451 ADDR_ASSERT(IsThin(resourceType, swizzleMode));
1452
1453 // GFX9/GFX10 use different dimension amplifying logic: say for 128KB block + 1xAA + 1BPE, the dimension of thin
1454 // swizzle mode will be [256W * 512H] on GFX9 ASICs and [512W * 256H] on GFX10 ASICs. Since GFX10 is newer HWL so we
1455 // make its implementation into base class (in order to save future change on new HWLs)
1456 const UINT_32 log2BlkSize = GetBlockSizeLog2(swizzleMode);
1457 const UINT_32 log2EleBytes = Log2(bpp >> 3);
1458 const UINT_32 log2Samples = Log2(Max(numSamples, 1u));
1459 const UINT_32 log2NumEle = log2BlkSize - log2EleBytes - log2Samples;
1460
1461 // For "1xAA/4xAA cases" or "2xAA/8xAA + odd log2BlkSize cases", width == height or width == 2 * height;
1462 // For other cases, height == width or height == 2 * width
1463 const BOOL_32 widthPrecedent = ((log2Samples & 1) == 0) || ((log2BlkSize & 1) != 0);
1464 const UINT_32 log2Width = (log2NumEle + (widthPrecedent ? 1 : 0)) / 2;
1465
1466 *pWidth = 1u << log2Width;
1467 *pHeight = 1u << (log2NumEle - log2Width);
1468 *pDepth = 1;
1469 }
1470
1471 /**
1472 ************************************************************************************************************************
1473 * Lib::ComputeBlockDimension
1474 *
1475 * @brief
1476 * Internal function to get block width/height/depth in element without considering MSAA case
1477 *
1478 * @return
1479 * ADDR_E_RETURNCODE
1480 ************************************************************************************************************************
1481 */
ComputeBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1482 ADDR_E_RETURNCODE Lib::ComputeBlockDimension(
1483 UINT_32* pWidth,
1484 UINT_32* pHeight,
1485 UINT_32* pDepth,
1486 UINT_32 bpp,
1487 AddrResourceType resourceType,
1488 AddrSwizzleMode swizzleMode) const
1489 {
1490 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1491
1492 if (IsThick(resourceType, swizzleMode))
1493 {
1494 ComputeThickBlockDimension(pWidth, pHeight, pDepth, bpp, resourceType, swizzleMode);
1495 }
1496 else if (IsThin(resourceType, swizzleMode))
1497 {
1498 ComputeThinBlockDimension(pWidth, pHeight, pDepth, bpp, 0, resourceType, swizzleMode);
1499 }
1500 else
1501 {
1502 ADDR_ASSERT_ALWAYS();
1503 returnCode = ADDR_INVALIDPARAMS;
1504 }
1505
1506 return returnCode;
1507 }
1508
1509 /**
1510 ************************************************************************************************************************
1511 * Lib::ComputeThickBlockDimension
1512 *
1513 * @brief
1514 * Internal function to get block width/height/depth in element for thick swizzle mode
1515 *
1516 * @return
1517 * N/A
1518 ************************************************************************************************************************
1519 */
ComputeThickBlockDimension(UINT_32 * pWidth,UINT_32 * pHeight,UINT_32 * pDepth,UINT_32 bpp,AddrResourceType resourceType,AddrSwizzleMode swizzleMode) const1520 VOID Lib::ComputeThickBlockDimension(
1521 UINT_32* pWidth,
1522 UINT_32* pHeight,
1523 UINT_32* pDepth,
1524 UINT_32 bpp,
1525 AddrResourceType resourceType,
1526 AddrSwizzleMode swizzleMode) const
1527 {
1528 ADDR_ASSERT(IsThick(resourceType, swizzleMode));
1529
1530 const UINT_32 log2BlkSize = GetBlockSizeLog2(swizzleMode);
1531 const UINT_32 eleBytes = bpp >> 3;
1532 const UINT_32 microBlockSizeTableIndex = Log2(eleBytes);
1533
1534 ADDR_ASSERT(microBlockSizeTableIndex < sizeof(Block1K_3d) / sizeof(Block1K_3d[0]));
1535
1536 const UINT_32 log2blkSizeIn1KB = log2BlkSize - 10;
1537 const UINT_32 averageAmp = log2blkSizeIn1KB / 3;
1538 const UINT_32 restAmp = log2blkSizeIn1KB % 3;
1539
1540 *pWidth = Block1K_3d[microBlockSizeTableIndex].w << averageAmp;
1541 *pHeight = Block1K_3d[microBlockSizeTableIndex].h << (averageAmp + (restAmp / 2));
1542 *pDepth = Block1K_3d[microBlockSizeTableIndex].d << (averageAmp + ((restAmp != 0) ? 1 : 0));
1543 }
1544
1545 /**
1546 ************************************************************************************************************************
1547 * Lib::GetMipTailDim
1548 *
1549 * @brief
1550 * Internal function to get out max dimension of first level in mip tail
1551 *
1552 * @return
1553 * Max Width/Height/Depth value of the first mip fitted in mip tail
1554 ************************************************************************************************************************
1555 */
GetMipTailDim(AddrResourceType resourceType,AddrSwizzleMode swizzleMode,UINT_32 blockWidth,UINT_32 blockHeight,UINT_32 blockDepth) const1556 Dim3d Lib::GetMipTailDim(
1557 AddrResourceType resourceType,
1558 AddrSwizzleMode swizzleMode,
1559 UINT_32 blockWidth,
1560 UINT_32 blockHeight,
1561 UINT_32 blockDepth) const
1562 {
1563 Dim3d out = {blockWidth, blockHeight, blockDepth};
1564 UINT_32 log2BlkSize = GetBlockSizeLog2(swizzleMode);
1565
1566 if (IsThick(resourceType, swizzleMode))
1567 {
1568 UINT_32 dim = log2BlkSize % 3;
1569
1570 if (dim == 0)
1571 {
1572 out.h >>= 1;
1573 }
1574 else if (dim == 1)
1575 {
1576 out.w >>= 1;
1577 }
1578 else
1579 {
1580 out.d >>= 1;
1581 }
1582 }
1583 else
1584 {
1585 ADDR_ASSERT(IsThin(resourceType, swizzleMode));
1586
1587 #if DEBUG
1588 // GFX9/GFX10 use different dimension shrinking logic for mipmap tail: say for 128KB block + 2BPE, the maximum
1589 // dimension of mipmap tail level will be [256W * 128H] on GFX9 ASICs and [128W * 256H] on GFX10 ASICs. Since
1590 // GFX10 is newer HWL so we make its implementation into base class, in order to save future change on new HWLs.
1591 // And assert log2BlkSize will always be an even value on GFX9, so we never need the logic wrapped by DEBUG...
1592 if ((log2BlkSize & 1) && (m_chipFamily == ADDR_CHIP_FAMILY_AI))
1593 {
1594 // Should never go here...
1595 ADDR_ASSERT_ALWAYS();
1596
1597 out.h >>= 1;
1598 }
1599 else
1600 #endif
1601 {
1602 out.w >>= 1;
1603 }
1604 }
1605
1606 return out;
1607 }
1608
1609 /**
1610 ************************************************************************************************************************
1611 * Lib::ComputeSurface2DMicroBlockOffset
1612 *
1613 * @brief
1614 * Internal function to calculate micro block (256B) offset from coord for 2D resource
1615 *
1616 * @return
1617 * micro block (256B) offset for 2D resource
1618 ************************************************************************************************************************
1619 */
ComputeSurface2DMicroBlockOffset(const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn) const1620 UINT_32 Lib::ComputeSurface2DMicroBlockOffset(
1621 const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
1622 {
1623 ADDR_ASSERT(IsThin(pIn->resourceType, pIn->swizzleMode));
1624
1625 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1626 UINT_32 microBlockOffset = 0;
1627 if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
1628 {
1629 UINT_32 xBits = pIn->x << log2ElementBytes;
1630 microBlockOffset = (xBits & 0xf) | ((pIn->y & 0x3) << 4);
1631 if (log2ElementBytes < 3)
1632 {
1633 microBlockOffset |= (pIn->y & 0x4) << 4;
1634 if (log2ElementBytes == 0)
1635 {
1636 microBlockOffset |= (pIn->y & 0x8) << 4;
1637 }
1638 else
1639 {
1640 microBlockOffset |= (xBits & 0x10) << 3;
1641 }
1642 }
1643 else
1644 {
1645 microBlockOffset |= (xBits & 0x30) << 2;
1646 }
1647 }
1648 else if (IsDisplaySwizzle(pIn->resourceType, pIn->swizzleMode))
1649 {
1650 if (log2ElementBytes == 4)
1651 {
1652 microBlockOffset = (GetBit(pIn->x, 0) << 4) |
1653 (GetBit(pIn->y, 0) << 5) |
1654 (GetBit(pIn->x, 1) << 6) |
1655 (GetBit(pIn->y, 1) << 7);
1656 }
1657 else
1658 {
1659 microBlockOffset = GetBits(pIn->x, 0, 3, log2ElementBytes) |
1660 GetBits(pIn->y, 1, 2, 3 + log2ElementBytes) |
1661 GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
1662 GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
1663 microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
1664 (GetBit(pIn->y, 0) << 4) |
1665 GetBits(microBlockOffset, 4, 3, 5);
1666 }
1667 }
1668 else if (IsRotateSwizzle(pIn->swizzleMode))
1669 {
1670 microBlockOffset = GetBits(pIn->y, 0, 3, log2ElementBytes) |
1671 GetBits(pIn->x, 1, 2, 3 + log2ElementBytes) |
1672 GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
1673 GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
1674 microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
1675 (GetBit(pIn->x, 0) << 4) |
1676 GetBits(microBlockOffset, 4, 3, 5);
1677 if (log2ElementBytes == 3)
1678 {
1679 microBlockOffset = GetBits(microBlockOffset, 0, 6, 0) |
1680 GetBits(pIn->x, 1, 2, 6);
1681 }
1682 }
1683
1684 return microBlockOffset;
1685 }
1686
1687 /**
1688 ************************************************************************************************************************
1689 * Lib::ComputeSurface3DMicroBlockOffset
1690 *
1691 * @brief
1692 * Internal function to calculate micro block (1KB) offset from coord for 3D resource
1693 *
1694 * @return
1695 * micro block (1KB) offset for 3D resource
1696 ************************************************************************************************************************
1697 */
ComputeSurface3DMicroBlockOffset(const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn) const1698 UINT_32 Lib::ComputeSurface3DMicroBlockOffset(
1699 const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
1700 {
1701 ADDR_ASSERT(IsThick(pIn->resourceType, pIn->swizzleMode));
1702
1703 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1704 UINT_32 microBlockOffset = 0;
1705 if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
1706 {
1707 if (log2ElementBytes == 0)
1708 {
1709 microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
1710 }
1711 else if (log2ElementBytes == 1)
1712 {
1713 microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
1714 }
1715 else if (log2ElementBytes == 2)
1716 {
1717 microBlockOffset = ((pIn->y & 4) >> 2) | ((pIn->x & 4) >> 1);
1718 }
1719 else if (log2ElementBytes == 3)
1720 {
1721 microBlockOffset = (pIn->x & 6) >> 1;
1722 }
1723 else
1724 {
1725 microBlockOffset = pIn->x & 3;
1726 }
1727
1728 microBlockOffset <<= 8;
1729
1730 UINT_32 xBits = pIn->x << log2ElementBytes;
1731 microBlockOffset |= (xBits & 0xf) | ((pIn->y & 0x3) << 4) | ((pIn->slice & 0x3) << 6);
1732 }
1733 else if (IsZOrderSwizzle(pIn->swizzleMode))
1734 {
1735 UINT_32 xh, yh, zh;
1736
1737 if (log2ElementBytes == 0)
1738 {
1739 microBlockOffset =
1740 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
1741 microBlockOffset = microBlockOffset | ((pIn->slice & 3) << 4) | ((pIn->x & 4) << 4);
1742
1743 xh = pIn->x >> 3;
1744 yh = pIn->y >> 2;
1745 zh = pIn->slice >> 2;
1746 }
1747 else if (log2ElementBytes == 1)
1748 {
1749 microBlockOffset =
1750 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
1751 microBlockOffset = (microBlockOffset << 1) | ((pIn->slice & 3) << 5);
1752
1753 xh = pIn->x >> 2;
1754 yh = pIn->y >> 2;
1755 zh = pIn->slice >> 2;
1756 }
1757 else if (log2ElementBytes == 2)
1758 {
1759 microBlockOffset =
1760 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->slice & 1) << 3);
1761 microBlockOffset = (microBlockOffset << 2) | ((pIn->y & 2) << 5);
1762
1763 xh = pIn->x >> 2;
1764 yh = pIn->y >> 2;
1765 zh = pIn->slice >> 1;
1766 }
1767 else if (log2ElementBytes == 3)
1768 {
1769 microBlockOffset =
1770 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2) | ((pIn->x & 2) << 2);
1771 microBlockOffset <<= 3;
1772
1773 xh = pIn->x >> 2;
1774 yh = pIn->y >> 1;
1775 zh = pIn->slice >> 1;
1776 }
1777 else
1778 {
1779 microBlockOffset =
1780 (((pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2)) << 4);
1781
1782 xh = pIn->x >> 1;
1783 yh = pIn->y >> 1;
1784 zh = pIn->slice >> 1;
1785 }
1786
1787 microBlockOffset |= ((MortonGen3d(xh, yh, zh, 1) << 7) & 0x380);
1788 }
1789
1790 return microBlockOffset;
1791 }
1792
1793 /**
1794 ************************************************************************************************************************
1795 * Lib::GetPipeXorBits
1796 *
1797 * @brief
1798 * Internal function to get bits number for pipe/se xor operation
1799 *
1800 * @return
1801 * ADDR_E_RETURNCODE
1802 ************************************************************************************************************************
1803 */
GetPipeXorBits(UINT_32 macroBlockBits) const1804 UINT_32 Lib::GetPipeXorBits(
1805 UINT_32 macroBlockBits) const
1806 {
1807 ADDR_ASSERT(macroBlockBits >= m_pipeInterleaveLog2);
1808
1809 // Total available xor bits
1810 UINT_32 xorBits = macroBlockBits - m_pipeInterleaveLog2;
1811
1812 // Pipe/Se xor bits
1813 UINT_32 pipeBits = Min(xorBits, m_pipesLog2 + m_seLog2);
1814
1815 return pipeBits;
1816 }
1817
1818 /**
1819 ************************************************************************************************************************
1820 * Lib::Addr2GetPreferredSurfaceSetting
1821 *
1822 * @brief
1823 * Internal function to get suggested surface information for cliet to use
1824 *
1825 * @return
1826 * ADDR_E_RETURNCODE
1827 ************************************************************************************************************************
1828 */
Addr2GetPreferredSurfaceSetting(const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT * pIn,ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT * pOut) const1829 ADDR_E_RETURNCODE Lib::Addr2GetPreferredSurfaceSetting(
1830 const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT* pIn,
1831 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT* pOut) const
1832 {
1833 ADDR_E_RETURNCODE returnCode;
1834
1835 if ((GetFillSizeFieldsFlags() == TRUE) &&
1836 ((pIn->size != sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_INPUT)) ||
1837 (pOut->size != sizeof(ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT))))
1838 {
1839 returnCode = ADDR_INVALIDPARAMS;
1840 }
1841 else
1842 {
1843 returnCode = HwlGetPreferredSurfaceSetting(pIn, pOut);
1844 }
1845
1846 return returnCode;
1847 }
1848
1849 /**
1850 ************************************************************************************************************************
1851 * Lib::GetPossibleSwizzleModes
1852 *
1853 * @brief
1854 * Returns a list of swizzle modes that are valid from the hardware's perspective for the client to choose from
1855 *
1856 * @return
1857 * ADDR_E_RETURNCODE
1858 ************************************************************************************************************************
1859 */
GetPossibleSwizzleModes(const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT * pIn,ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT * pOut) const1860 ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes(
1861 const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT* pIn,
1862 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT* pOut) const
1863 {
1864 return HwlGetPossibleSwizzleModes(pIn, pOut);
1865 }
1866
1867 /**
1868 ************************************************************************************************************************
1869 * Lib::GetAllowedBlockSet
1870 *
1871 * @brief
1872 * Returns the set of allowed block sizes given the allowed swizzle modes and resource type
1873 *
1874 * @return
1875 * ADDR_E_RETURNCODE
1876 ************************************************************************************************************************
1877 */
GetAllowedBlockSet(ADDR2_SWMODE_SET allowedSwModeSet,AddrResourceType rsrcType,ADDR2_BLOCK_SET * pAllowedBlockSet) const1878 ADDR_E_RETURNCODE Lib::GetAllowedBlockSet(
1879 ADDR2_SWMODE_SET allowedSwModeSet,
1880 AddrResourceType rsrcType,
1881 ADDR2_BLOCK_SET* pAllowedBlockSet) const
1882 {
1883 return HwlGetAllowedBlockSet(allowedSwModeSet, rsrcType, pAllowedBlockSet);
1884 }
1885
1886 /**
1887 ************************************************************************************************************************
1888 * Lib::GetAllowedSwSet
1889 *
1890 * @brief
1891 * Returns the set of allowed swizzle types given the allowed swizzle modes
1892 *
1893 * @return
1894 * ADDR_E_RETURNCODE
1895 ************************************************************************************************************************
1896 */
GetAllowedSwSet(ADDR2_SWMODE_SET allowedSwModeSet,ADDR2_SWTYPE_SET * pAllowedSwSet) const1897 ADDR_E_RETURNCODE Lib::GetAllowedSwSet(
1898 ADDR2_SWMODE_SET allowedSwModeSet,
1899 ADDR2_SWTYPE_SET* pAllowedSwSet) const
1900 {
1901 return HwlGetAllowedSwSet(allowedSwModeSet, pAllowedSwSet);
1902 }
1903
1904 /**
1905 ************************************************************************************************************************
1906 * Lib::ComputeBlock256Equation
1907 *
1908 * @brief
1909 * Compute equation for block 256B
1910 *
1911 * @return
1912 * If equation computed successfully
1913 *
1914 ************************************************************************************************************************
1915 */
ComputeBlock256Equation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1916 ADDR_E_RETURNCODE Lib::ComputeBlock256Equation(
1917 AddrResourceType rsrcType,
1918 AddrSwizzleMode swMode,
1919 UINT_32 elementBytesLog2,
1920 ADDR_EQUATION* pEquation) const
1921 {
1922 ADDR_E_RETURNCODE ret;
1923
1924 if (IsBlock256b(swMode))
1925 {
1926 ret = HwlComputeBlock256Equation(rsrcType, swMode, elementBytesLog2, pEquation);
1927 }
1928 else
1929 {
1930 ADDR_ASSERT_ALWAYS();
1931 ret = ADDR_INVALIDPARAMS;
1932 }
1933
1934 return ret;
1935 }
1936
1937 /**
1938 ************************************************************************************************************************
1939 * Lib::ComputeThinEquation
1940 *
1941 * @brief
1942 * Compute equation for 2D/3D resource which use THIN mode
1943 *
1944 * @return
1945 * If equation computed successfully
1946 *
1947 ************************************************************************************************************************
1948 */
ComputeThinEquation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1949 ADDR_E_RETURNCODE Lib::ComputeThinEquation(
1950 AddrResourceType rsrcType,
1951 AddrSwizzleMode swMode,
1952 UINT_32 elementBytesLog2,
1953 ADDR_EQUATION* pEquation) const
1954 {
1955 ADDR_E_RETURNCODE ret;
1956
1957 if (IsThin(rsrcType, swMode))
1958 {
1959 ret = HwlComputeThinEquation(rsrcType, swMode, elementBytesLog2, pEquation);
1960 }
1961 else
1962 {
1963 ADDR_ASSERT_ALWAYS();
1964 ret = ADDR_INVALIDPARAMS;
1965 }
1966
1967 return ret;
1968 }
1969
1970 /**
1971 ************************************************************************************************************************
1972 * Lib::ComputeThickEquation
1973 *
1974 * @brief
1975 * Compute equation for 3D resource which use THICK mode
1976 *
1977 * @return
1978 * If equation computed successfully
1979 *
1980 ************************************************************************************************************************
1981 */
ComputeThickEquation(AddrResourceType rsrcType,AddrSwizzleMode swMode,UINT_32 elementBytesLog2,ADDR_EQUATION * pEquation) const1982 ADDR_E_RETURNCODE Lib::ComputeThickEquation(
1983 AddrResourceType rsrcType,
1984 AddrSwizzleMode swMode,
1985 UINT_32 elementBytesLog2,
1986 ADDR_EQUATION* pEquation) const
1987 {
1988 ADDR_E_RETURNCODE ret;
1989
1990 if (IsThick(rsrcType, swMode))
1991 {
1992 ret = HwlComputeThickEquation(rsrcType, swMode, elementBytesLog2, pEquation);
1993 }
1994 else
1995 {
1996 ADDR_ASSERT_ALWAYS();
1997 ret = ADDR_INVALIDPARAMS;
1998 }
1999
2000 return ret;
2001 }
2002
2003 /**
2004 ************************************************************************************************************************
2005 * Lib::ComputeQbStereoInfo
2006 *
2007 * @brief
2008 * Get quad buffer stereo information
2009 * @return
2010 * N/A
2011 ************************************************************************************************************************
2012 */
ComputeQbStereoInfo(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2013 VOID Lib::ComputeQbStereoInfo(
2014 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] updated pOut+pStereoInfo
2015 ) const
2016 {
2017 ADDR_ASSERT(pOut->bpp >= 8);
2018 ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
2019
2020 // Save original height
2021 pOut->pStereoInfo->eyeHeight = pOut->height;
2022
2023 // Right offset
2024 pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
2025
2026 // Double height
2027 pOut->height <<= 1;
2028
2029 ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
2030
2031 pOut->pixelHeight <<= 1;
2032
2033 // Double size
2034 pOut->surfSize <<= 1;
2035 pOut->sliceSize <<= 1;
2036 }
2037
2038 /**
2039 ************************************************************************************************************************
2040 * Lib::FilterInvalidEqSwizzleMode
2041 *
2042 * @brief
2043 * Filter out swizzle mode(s) if it doesn't have valid equation index
2044 *
2045 * @return
2046 * N/A
2047 ************************************************************************************************************************
2048 */
FilterInvalidEqSwizzleMode(ADDR2_SWMODE_SET & allowedSwModeSet,AddrResourceType resourceType,UINT_32 elemLog2,UINT_32 maxComponents) const2049 VOID Lib::FilterInvalidEqSwizzleMode(
2050 ADDR2_SWMODE_SET& allowedSwModeSet,
2051 AddrResourceType resourceType,
2052 UINT_32 elemLog2,
2053 UINT_32 maxComponents
2054 ) const
2055 {
2056 if (resourceType != ADDR_RSRC_TEX_1D)
2057 {
2058 UINT_32 allowedSwModeSetVal = allowedSwModeSet.value;
2059 const UINT_32 rsrcTypeIdx = static_cast<UINT_32>(resourceType) - 1;
2060 UINT_32 validSwModeSet = allowedSwModeSetVal;
2061
2062 for (UINT_32 swModeIdx = 1; validSwModeSet != 0; swModeIdx++)
2063 {
2064 if (validSwModeSet & 1)
2065 {
2066 UINT_32 equation = m_equationLookupTable[rsrcTypeIdx][swModeIdx][elemLog2];
2067 if (equation == ADDR_INVALID_EQUATION_INDEX)
2068 {
2069 allowedSwModeSetVal &= ~(1u << swModeIdx);
2070 }
2071 else if (m_equationTable[equation].numBitComponents > maxComponents)
2072 {
2073 allowedSwModeSetVal &= ~(1u << swModeIdx);
2074 }
2075 }
2076
2077 validSwModeSet >>= 1;
2078 }
2079
2080 // Only apply the filtering if at least one valid swizzle mode remains
2081 if (allowedSwModeSetVal != 0)
2082 {
2083 allowedSwModeSet.value = allowedSwModeSetVal;
2084 }
2085 }
2086 }
2087
2088 #if DEBUG
2089 /**
2090 ************************************************************************************************************************
2091 * Lib::ValidateStereoInfo
2092 *
2093 * @brief
2094 * Validate stereo info by checking a few typical cases
2095 *
2096 * @return
2097 * N/A
2098 ************************************************************************************************************************
2099 */
ValidateStereoInfo(const ADDR2_COMPUTE_SURFACE_INFO_INPUT * pIn,const ADDR2_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const2100 VOID Lib::ValidateStereoInfo(
2101 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
2102 const ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in] output structure
2103 ) const
2104 {
2105 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT addrIn = {};
2106 addrIn.size = sizeof(addrIn);
2107 addrIn.swizzleMode = pIn->swizzleMode;
2108 addrIn.flags = pIn->flags;
2109 addrIn.flags.qbStereo = 0;
2110 addrIn.resourceType = pIn->resourceType;
2111 addrIn.bpp = pIn->bpp;
2112 addrIn.unalignedWidth = pIn->width;
2113 addrIn.numSlices = pIn->numSlices;
2114 addrIn.numMipLevels = pIn->numMipLevels;
2115 addrIn.numSamples = pIn->numSamples;
2116 addrIn.numFrags = pIn->numFrags;
2117
2118 // Call Addr2ComputePipeBankXor() and validate different pbXor value if necessary...
2119 const UINT_32 pbXor = 0;
2120
2121 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT addrOut = {};
2122 addrOut.size = sizeof(addrOut);
2123
2124 // Make the array to be {0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096} for full test
2125 const UINT_32 TestCoord[] = {0};
2126
2127 for (UINT_32 xIdx = 0; xIdx < sizeof(TestCoord) / sizeof(TestCoord[0]); xIdx++)
2128 {
2129 if (TestCoord[xIdx] < pIn->width)
2130 {
2131 addrIn.x = TestCoord[xIdx];
2132
2133 for (UINT_32 yIdx = 0; yIdx < sizeof(TestCoord) / sizeof(TestCoord[0]); yIdx++)
2134 {
2135 if (TestCoord[yIdx] < pIn->height)
2136 {
2137 addrIn.y = TestCoord[yIdx] + pOut->pStereoInfo->eyeHeight;
2138 addrIn.pipeBankXor = pbXor ^ pOut->pStereoInfo->rightSwizzle;
2139 addrIn.unalignedHeight = pIn->height + pOut->pStereoInfo->eyeHeight;
2140
2141 ADDR_E_RETURNCODE ret = ComputeSurfaceAddrFromCoord(&addrIn, &addrOut);
2142 ADDR_ASSERT(ret == ADDR_OK);
2143
2144 const UINT_64 rightEyeOffsetFromBase = addrOut.addr;
2145
2146 addrIn.y = TestCoord[yIdx];
2147 addrIn.pipeBankXor = pbXor;
2148 addrIn.unalignedHeight = pIn->height;
2149
2150 ret = ComputeSurfaceAddrFromCoord(&addrIn, &addrOut);
2151 ADDR_ASSERT(ret == ADDR_OK);
2152
2153 const UINT_64 rightEyeOffsetRelative = addrOut.addr;
2154
2155 ADDR_ASSERT(rightEyeOffsetFromBase == rightEyeOffsetRelative + pOut->pStereoInfo->rightOffset);
2156 }
2157 }
2158 }
2159 }
2160 }
2161 #endif
2162
2163 } // V2
2164 } // Addr
2165
2166