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