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 addrlib3.cpp
13 * @brief Contains the implementation for the AddrLib3 base class.
14 ************************************************************************************************************************
15 */
16
17 #include "addrinterface.h"
18 #include "addrlib3.h"
19 #include "addrcommon.h"
20
21 namespace Addr
22 {
23 namespace V3
24 {
25
26 ////////////////////////////////////////////////////////////////////////////////////////////////////
27 // Constructor/Destructor
28 ////////////////////////////////////////////////////////////////////////////////////////////////////
29
30 /**
31 ************************************************************************************************************************
32 * Lib::Lib
33 *
34 * @brief
35 * Constructor for the Addr::V3::Lib class
36 *
37 ************************************************************************************************************************
38 */
Lib()39 Lib::Lib()
40 :
41 Addr::Lib(),
42 m_pipesLog2(0),
43 m_pipeInterleaveLog2(0),
44 m_numEquations(0)
45 {
46 Init();
47 }
48
49 /**
50 ************************************************************************************************************************
51 * Lib::Lib
52 *
53 * @brief
54 * Constructor for the AddrLib3 class with hClient as parameter
55 *
56 ************************************************************************************************************************
57 */
Lib(const Client * pClient)58 Lib::Lib(
59 const Client* pClient)
60 :
61 Addr::Lib(pClient),
62 m_pipesLog2(0),
63 m_pipeInterleaveLog2(0),
64 m_numEquations(0)
65 {
66 Init();
67 }
68
69 /**
70 ************************************************************************************************************************
71 * Lib::Init
72 *
73 * @brief
74 * Initialization of class
75 *
76 ************************************************************************************************************************
77 */
Init()78 void Lib::Init()
79 {
80 memset(m_blockDimensionTable, 0, sizeof(m_blockDimensionTable));
81
82 // There is no equation table entry for linear, so start at the "next" swizzle mode entry.
83 for (UINT_32 swizzleModeIdx = ADDR3_LINEAR + 1; swizzleModeIdx < ADDR3_MAX_TYPE; swizzleModeIdx++)
84 {
85 for (UINT_32 msaaRateIdx = 0; msaaRateIdx < MaxMsaaRateLog2; msaaRateIdx++)
86 {
87 for (UINT_32 log2BytesIdx = 0; log2BytesIdx < MaxElementBytesLog2; log2BytesIdx++)
88 {
89 SetEquationTableEntry(static_cast<Addr3SwizzleMode>(swizzleModeIdx),
90 msaaRateIdx,
91 log2BytesIdx,
92 ADDR_INVALID_EQUATION_INDEX);
93 }
94 }
95 }
96 }
97
98 /**
99 ************************************************************************************************************************
100 * Lib::~Lib
101 *
102 * @brief
103 * Destructor for the AddrLib2 class
104 *
105 ************************************************************************************************************************
106 */
~Lib()107 Lib::~Lib()
108 {
109 }
110
111 /**
112 ************************************************************************************************************************
113 * Lib::GetLib
114 *
115 * @brief
116 * Get Addr::V3::Lib pointer
117 *
118 * @return
119 * An Addr::V2::Lib class pointer
120 ************************************************************************************************************************
121 */
GetLib(ADDR_HANDLE hLib)122 Lib* Lib::GetLib(
123 ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE
124 {
125 Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib);
126
127 return static_cast<Lib*>(pAddrLib);
128 }
129
130 /**
131 ************************************************************************************************************************
132 * Lib::GetBlockSize
133 *
134 * @brief
135 * Returns the byte size of a block for the swizzle mode.
136 *
137 * @return
138 * Byte size of the block, zero if swizzle mode is invalid.
139 ************************************************************************************************************************
140 */
GetBlockSize(Addr3SwizzleMode swizzleMode,BOOL_32 forPitch) const141 UINT_32 Lib::GetBlockSize(
142 Addr3SwizzleMode swizzleMode,
143 BOOL_32 forPitch
144 ) const
145 {
146 return (1 << GetBlockSizeLog2(swizzleMode, forPitch));
147 }
148
149 /**
150 ************************************************************************************************************************
151 * Lib::GetBlockSizeLog2
152 *
153 * @brief
154 * Returns the log2 of the byte size of a block for the swizzle mode.
155 *
156 * @return
157 * Byte size of the block, zero if swizzle mode is invalid.
158 ************************************************************************************************************************
159 */
GetBlockSizeLog2(Addr3SwizzleMode swizzleMode,BOOL_32 forPitch) const160 UINT_32 Lib::GetBlockSizeLog2(
161 Addr3SwizzleMode swizzleMode,
162 BOOL_32 forPitch
163 ) const
164 {
165 UINT_32 blockSize = 0;
166
167 switch (swizzleMode)
168 {
169 case ADDR3_256B_2D:
170 blockSize = 8;
171 break;
172 case ADDR3_4KB_2D:
173 case ADDR3_4KB_3D:
174 blockSize = 12;
175 break;
176 case ADDR3_64KB_2D:
177 case ADDR3_64KB_3D:
178 blockSize = 16;
179 break;
180 case ADDR3_256KB_2D:
181 case ADDR3_256KB_3D:
182 blockSize = 18;
183 break;
184 case ADDR3_LINEAR:
185 blockSize = (forPitch ? 7 : 8);
186 break;
187 default:
188 ADDR_ASSERT_ALWAYS();
189 break;
190 }
191
192 return blockSize;
193 }
194
195 /**
196 ************************************************************************************************************************
197 * Lib::ComputeSurfaceInfo
198 *
199 * @brief
200 * Interface function stub of ComputeSurfaceInfo.
201 *
202 * @return
203 * ADDR_E_RETURNCODE
204 ************************************************************************************************************************
205 */
ComputeSurfaceInfo(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const206 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo(
207 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
208 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
209 ) const
210 {
211 ADDR_E_RETURNCODE returnCode = ADDR_OK;
212
213 if (GetFillSizeFieldsFlags() == TRUE)
214 {
215 if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_INPUT)) ||
216 (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT)))
217 {
218 returnCode = ADDR_PARAMSIZEMISMATCH;
219 }
220 }
221
222 // Adjust incoming parameters.
223 ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
224 localIn.width = Max(pIn->width, 1u);
225 localIn.height = Max(pIn->height, 1u);
226 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
227 localIn.numSlices = Max(pIn->numSlices, 1u);
228 localIn.numSamples = Max(pIn->numSamples, 1u);
229
230 UINT_32 expandX = 1;
231 UINT_32 expandY = 1;
232 ElemMode elemMode = ADDR_UNCOMPRESSED;
233
234 if (returnCode == ADDR_OK)
235 {
236 // Set format to INVALID will skip this conversion
237 if (localIn.format != ADDR_FMT_INVALID)
238 {
239 // Get compression/expansion factors and element mode which indicates compression/expansion
240 localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
241 &elemMode,
242 &expandX,
243 &expandY);
244
245 // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
246 // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
247 // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
248 // restrictions are different.
249 // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
250 // but we use this flag to skip RestoreSurfaceInfo below
251 if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
252 {
253 ADDR_ASSERT(IsLinear(localIn.swizzleMode));
254 }
255
256 UINT_32 basePitch = 0;
257 GetElemLib()->AdjustSurfaceInfo(elemMode,
258 expandX,
259 expandY,
260 &localIn.bpp,
261 &basePitch,
262 &localIn.width,
263 &localIn.height);
264
265 // Overwrite these parameters if we have a valid format
266 }
267
268 if (localIn.bpp != 0)
269 {
270 localIn.width = Max(localIn.width, 1u);
271 localIn.height = Max(localIn.height, 1u);
272 }
273 else // Rule out some invalid parameters
274 {
275 returnCode = ADDR_INVALIDPARAMS;
276 }
277 }
278
279 if (returnCode == ADDR_OK)
280 {
281 returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
282
283 if (returnCode == ADDR_OK)
284 {
285 pOut->bpp = localIn.bpp;
286 pOut->pixelPitch = pOut->pitch;
287 pOut->pixelHeight = pOut->height;
288
289 if (localIn.format != ADDR_FMT_INVALID)
290 {
291 UINT_32 pixelBits = pOut->pixelBits;
292
293 GetElemLib()->RestoreSurfaceInfo(elemMode,
294 expandX,
295 expandY,
296 &pOut->pixelBits,
297 &pOut->pixelPitch,
298 &pOut->pixelHeight);
299
300 GetElemLib()->RestoreSurfaceInfo(elemMode,
301 expandX,
302 expandY,
303 &pixelBits,
304 &pOut->pixelMipChainPitch,
305 &pOut->pixelMipChainHeight);
306
307 if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL))
308 {
309 for (UINT_32 i = 0; i < localIn.numMipLevels; i++)
310 {
311 pOut->pMipInfo[i].pixelPitch = pOut->pMipInfo[i].pitch;
312 pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height;
313
314 GetElemLib()->RestoreSurfaceInfo(elemMode,
315 expandX,
316 expandY,
317 &pixelBits,
318 &pOut->pMipInfo[i].pixelPitch,
319 &pOut->pMipInfo[i].pixelHeight);
320 }
321 }
322
323 if (localIn.flags.qbStereo && (pOut->pStereoInfo != NULL))
324 {
325 ComputeQbStereoInfo(pOut);
326 }
327 }
328
329 SetEquationIndex(&localIn, pOut);
330 }
331 }
332
333 return returnCode;
334 }
335
336 /**
337 ************************************************************************************************************************
338 * Lib::GetPossibleSwizzleModes
339 *
340 * @brief
341 * Populates pOut with a list of the possible swizzle modes for the described surface.
342 *
343 * @return
344 * ADDR_E_RETURNCODE
345 ************************************************************************************************************************
346 */
GetPossibleSwizzleModes(const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT * pIn,ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT * pOut) const347 ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes(
348 const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn,
349 ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut
350 ) const
351 {
352 ADDR_E_RETURNCODE returnCode = ADDR_OK;
353
354 if (GetFillSizeFieldsFlags() == TRUE)
355 {
356 if ((pIn->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT)) ||
357 (pOut->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT)))
358 {
359 returnCode = ADDR_PARAMSIZEMISMATCH;
360 }
361 }
362
363 if ((returnCode == ADDR_OK) && (HwlValidateNonSwModeParams(pIn) == FALSE))
364 {
365 returnCode = ADDR_INVALIDPARAMS;
366 }
367
368 if (returnCode == ADDR_OK)
369 {
370 returnCode = HwlGetPossibleSwizzleModes(pIn, pOut);
371 }
372
373 return returnCode;
374 }
375
376 /**
377 ************************************************************************************************************************
378 * Lib::ComputeBlockDimensionForSurf
379 *
380 * @brief
381 * Internal function to get block width/height/depth in elements from surface input params.
382 *
383 * @return
384 * VOID
385 ************************************************************************************************************************
386 */
ComputeBlockDimensionForSurf(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,ADDR_EXTENT3D * pExtent) const387 VOID Lib::ComputeBlockDimensionForSurf(
388 const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
389 ADDR_EXTENT3D* pExtent
390 ) const
391 {
392 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo;
393 const UINT_32 log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode);
394
395 HwlCalcBlockSize(pIn, pExtent);
396 }
397
398 /**
399 ************************************************************************************************************************
400 * Lib::GetMipTailDim
401 *
402 * @brief
403 * Internal function to get out max dimension of first level in mip tail
404 *
405 * @return
406 * Max Width/Height/Depth value of the first mip fitted in mip tail
407 ************************************************************************************************************************
408 */
GetMipTailDim(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,const ADDR_EXTENT3D & blockDims) const409 ADDR_EXTENT3D Lib::GetMipTailDim(
410 const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
411 const ADDR_EXTENT3D& blockDims
412 ) const
413 {
414 return HwlGetMipInTailMaxSize(pIn, blockDims);
415 }
416
417 /**
418 ************************************************************************************************************************
419 * Lib::ComputeSurfaceAddrFromCoord
420 *
421 * @brief
422 * Interface function stub of ComputeSurfaceAddrFromCoord.
423 *
424 * @return
425 * ADDR_E_RETURNCODE
426 ************************************************************************************************************************
427 */
ComputeSurfaceAddrFromCoord(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const428 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
429 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
430 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
431 ) const
432 {
433 ADDR_E_RETURNCODE returnCode = ADDR_OK;
434
435 if (GetFillSizeFieldsFlags() == TRUE)
436 {
437 if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
438 (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
439 {
440 returnCode = ADDR_PARAMSIZEMISMATCH;
441 }
442 }
443
444 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
445 localIn.unAlignedDims.width = Max(pIn->unAlignedDims.width, 1u);
446 localIn.unAlignedDims.height = Max(pIn->unAlignedDims.height, 1u);
447 localIn.unAlignedDims.depth = Max(pIn->unAlignedDims.depth, 1u);
448 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
449 localIn.numSamples = Max(pIn->numSamples, 1u);
450
451 if ((localIn.bpp < 8) ||
452 (localIn.bpp > 128) ||
453 ((localIn.bpp % 8) != 0) ||
454 (localIn.sample >= localIn.numSamples) ||
455 (localIn.slice >= localIn.unAlignedDims.depth) ||
456 (localIn.mipId >= localIn.numMipLevels) ||
457 (IsTex3d(localIn.resourceType) &&
458 (Valid3DMipSliceIdConstraint(localIn.unAlignedDims.depth, localIn.mipId, localIn.slice) == FALSE)))
459 {
460 returnCode = ADDR_INVALIDPARAMS;
461 }
462
463 if (returnCode == ADDR_OK)
464 {
465 if (IsLinear(localIn.swizzleMode))
466 {
467 returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
468 }
469 else
470 {
471 returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
472 }
473
474 if (returnCode == ADDR_OK)
475 {
476 pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
477 }
478 }
479
480 return returnCode;
481 }
482
483 /**
484 ************************************************************************************************************************
485 * Lib::ComputeSurfaceAddrFromCoord
486 *
487 * @brief
488 * Interface function stub of Addr3ComputePipeBankXor.
489 *
490 * @return
491 * ADDR_E_RETURNCODE
492 ************************************************************************************************************************
493 */
ComputePipeBankXor(const ADDR3_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)494 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
495 const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn,
496 ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut)
497 {
498 ADDR_E_RETURNCODE returnCode;
499
500 if ((GetFillSizeFieldsFlags() == TRUE) &&
501 ((pIn->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_INPUT)) ||
502 (pOut->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT))))
503 {
504 returnCode = ADDR_INVALIDPARAMS;
505 }
506 else
507 {
508 returnCode = HwlComputePipeBankXor(pIn, pOut);
509 }
510
511 return returnCode;
512 }
513
514 /**
515 ************************************************************************************************************************
516 * Lib::ComputeSurfaceAddrFromCoordLinear
517 *
518 * @brief
519 * Internal function to calculate address from coord for linear swizzle surface
520 *
521 * @return
522 * ADDR_E_RETURNCODE
523 ************************************************************************************************************************
524 */
ComputeSurfaceAddrFromCoordLinear(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const525 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
526 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
527 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
528 ) const
529 {
530 ADDR_E_RETURNCODE returnCode = ADDR_OK;
531 BOOL_32 valid = (pIn->numSamples <= 1);
532
533 if (valid)
534 {
535 if (IsTex1d(pIn->resourceType))
536 {
537 valid = (pIn->y == 0);
538 }
539 }
540
541 if (valid)
542 {
543 ADDR3_COMPUTE_SURFACE_INFO_INPUT surfInfoIn = {0};
544
545 surfInfoIn.size = sizeof(surfInfoIn);
546 surfInfoIn.flags = pIn->flags;
547 surfInfoIn.swizzleMode = ADDR3_LINEAR;
548 surfInfoIn.resourceType = pIn->resourceType;
549 surfInfoIn.format = ADDR_FMT_INVALID;
550 surfInfoIn.bpp = pIn->bpp;
551 surfInfoIn.width = Max(pIn->unAlignedDims.width, 1u);
552 surfInfoIn.height = Max(pIn->unAlignedDims.height, 1u);
553 surfInfoIn.numSlices = Max(pIn->unAlignedDims.depth, 1u);
554 surfInfoIn.numMipLevels = Max(pIn->numMipLevels, 1u);
555 surfInfoIn.numSamples = Max(pIn->numSamples, 1u);
556
557 if (surfInfoIn.numMipLevels <= 1)
558 {
559 surfInfoIn.pitchInElement = pIn->pitchInElement;
560 }
561
562 returnCode = HwlComputeSurfaceAddrFromCoordLinear(pIn, &surfInfoIn, pOut);
563 }
564
565 if (valid == FALSE)
566 {
567 returnCode = ADDR_INVALIDPARAMS;
568 }
569
570 return returnCode;
571 }
572
573 /**
574 ************************************************************************************************************************
575 * Lib::ComputeSurfaceAddrFromCoordTiled
576 *
577 * @brief
578 * Internal function to calculate address from coord for tiled swizzle surface
579 *
580 * @return
581 * ADDR_E_RETURNCODE
582 ************************************************************************************************************************
583 */
ComputeSurfaceAddrFromCoordTiled(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const584 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
585 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
586 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
587 ) const
588 {
589 return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
590 }
591
592 /**
593 ************************************************************************************************************************
594 * Lib::ComputeNonBlockCompressedView
595 *
596 * @brief
597 * Interface function stub of Addr3ComputeNonBlockCompressedView.
598 *
599 * @return
600 * ADDR_E_RETURNCODE
601 ************************************************************************************************************************
602 */
ComputeNonBlockCompressedView(const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)603 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
604 const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
605 ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut)
606 {
607 ADDR_E_RETURNCODE returnCode;
608
609 if ((GetFillSizeFieldsFlags() == TRUE) &&
610 ((pIn->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
611 (pOut->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
612 {
613 returnCode = ADDR_INVALIDPARAMS;
614 }
615 else if (Is3dSwizzle(pIn->swizzleMode))
616 {
617 // 3D volume images using ADDR3_XX_3D is currently not supported.
618 returnCode = ADDR_NOTSUPPORTED;
619 }
620 else
621 {
622 returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
623 }
624
625 return returnCode;
626 }
627
628 /**
629 ************************************************************************************************************************
630 * Lib::ComputeSubResourceOffsetForSwizzlePattern
631 *
632 * @brief
633 * Interface function stub of Addr3ComputeSubResourceOffsetForSwizzlePattern.
634 *
635 * @return
636 * ADDR_E_RETURNCODE
637 ************************************************************************************************************************
638 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)639 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
640 const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
641 ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut)
642 {
643 ADDR_E_RETURNCODE returnCode = ADDR_OK;
644
645 if ((GetFillSizeFieldsFlags() == TRUE) &&
646 ((pIn->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
647 (pOut->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
648 {
649 returnCode = ADDR_INVALIDPARAMS;
650 }
651 else
652 {
653 HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
654 }
655
656 return returnCode;
657 }
658
659 /**
660 ************************************************************************************************************************
661 * Lib::ComputeSlicePipeBankXor
662 *
663 * @brief
664 * Interface function stub of Addr3ComputeSlicePipeBankXor.
665 *
666 * @return
667 * ADDR_E_RETURNCODE
668 ************************************************************************************************************************
669 */
ComputeSlicePipeBankXor(const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)670 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
671 const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
672 ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut)
673 {
674 ADDR_E_RETURNCODE returnCode;
675
676 if ((GetFillSizeFieldsFlags() == TRUE) &&
677 ((pIn->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
678 (pOut->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
679 {
680 returnCode = ADDR_INVALIDPARAMS;
681 }
682 if ((pIn->bpe != 0) &&
683 (pIn->bpe != 8) &&
684 (pIn->bpe != 16) &&
685 (pIn->bpe != 32) &&
686 (pIn->bpe != 64) &&
687 (pIn->bpe != 128))
688 {
689 returnCode = ADDR_INVALIDPARAMS;
690 }
691 else
692 {
693 returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
694 }
695
696 return returnCode;
697 }
698
699 /**
700 ************************************************************************************************************************
701 * Lib::UseCustomHeight
702 *
703 * @brief
704 * Determines if the calculations for this surface should use minimal HW values or user-specified values.
705 *
706 * @return
707 * Returns TRUE if the user-specified alignment should be used
708 ************************************************************************************************************************
709 */
UseCustomHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const710 BOOL_32 Lib::UseCustomHeight(
711 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
712 ) const
713 {
714 return ((pIn->numMipLevels <= 1) &&
715 IsLinear(pIn->swizzleMode) &&
716 (pIn->sliceAlign > 0));
717 }
718
719 /**
720 ************************************************************************************************************************
721 * Lib::UseCustomPitch
722 *
723 * @brief
724 * Determines if the calculations for this surface should use minimal HW values or user-specified values.
725 *
726 * @return
727 * Returns TRUE if the user-specified pitch should be used
728 ************************************************************************************************************************
729 */
UseCustomPitch(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const730 BOOL_32 Lib::UseCustomPitch(
731 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
732 ) const
733 {
734 return ((pIn->numMipLevels <= 1) &&
735 IsLinear(pIn->swizzleMode) &&
736 (pIn->pitchInElement > 0));
737 }
738
739 /**
740 ************************************************************************************************************************
741 * Lib::CanTrimLinearPadding
742 *
743 * @brief
744 * Determines if the calculations for this surface can omit extra trailing padding for linear surfaces.
745 *
746 * @return
747 * Returns TRUE if the trailing padding can be omitted.
748 ************************************************************************************************************************
749 */
CanTrimLinearPadding(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const750 BOOL_32 Lib::CanTrimLinearPadding(
751 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
752 ) const
753 {
754 return ((IsTex3d(pIn->resourceType) == FALSE) &&
755 (pIn->numSlices <= 1) &&
756 IsLinear(pIn->swizzleMode));
757 }
758
759 /**
760 ************************************************************************************************************************
761 * Lib::ApplyCustomizedPitchHeight
762 *
763 * @brief
764 * Helper function to override hw required row pitch/slice pitch by customrized one
765 *
766 * @return
767 * ADDR_E_RETURNCODE
768 ************************************************************************************************************************
769 */
ApplyCustomizedPitchHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const770 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
771 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
772 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut
773 ) const
774 {
775 ADDR_E_RETURNCODE returnCode = ADDR_OK;
776
777 const UINT_32 elementBytes = pIn->bpp >> 3;
778
779 // Normal pitch of image data
780 const UINT_32 pitchAlignmentBytes = 1 << GetBlockSizeLog2(pIn->swizzleMode, TRUE);
781 const UINT_32 pitchAlignmentElements = pitchAlignmentBytes / elementBytes;
782 pOut->pitch = PowTwoAlign(pIn->width, pitchAlignmentElements);
783
784 // Pitch of image data used for slice sizing (same except for linear images)
785 const UINT_32 pitchSliceAlignmentBytes = 1 << GetBlockSizeLog2(pIn->swizzleMode, CanTrimLinearPadding(pIn));
786 const UINT_32 pitchSliceAlignmentElements = pitchSliceAlignmentBytes / elementBytes;
787 pOut->pitchForSlice = PowTwoAlign(pIn->width, pitchSliceAlignmentElements);
788
789 UINT_32 heightAlign = pOut->blockExtent.height;
790
791 if (pIn->flags.qbStereo)
792 {
793 UINT_32 rightXor = 0;
794
795 returnCode = HwlComputeStereoInfo(pIn, &heightAlign, &rightXor);
796
797 if (returnCode == ADDR_OK)
798 {
799 pOut->pStereoInfo->rightSwizzle = rightXor;
800 }
801 }
802
803 pOut->height = PowTwoAlign(pIn->height, heightAlign);
804
805 // Custom pitches / alignments are only possible with single mip level / linear images; otherwise,
806 // ignore those parameters.
807 if ((returnCode == ADDR_OK) && UseCustomPitch(pIn))
808 {
809 // Their requested pitch has to meet the pitch alignment constraints applied by the HW.
810 if ((pIn->pitchInElement % pitchAlignmentElements) != 0)
811 {
812 returnCode = ADDR_INVALIDPARAMS;
813 }
814 // And their pitch can't be less than the minimum
815 else if (pIn->pitchInElement < pOut->pitch)
816 {
817 returnCode = ADDR_INVALIDPARAMS;
818 }
819 else
820 {
821 pOut->pitch = pIn->pitchInElement;
822 pOut->pitchForSlice = PowTwoAlign(pIn->pitchInElement, pitchSliceAlignmentElements);
823 }
824 }
825
826 if ((returnCode == ADDR_OK) && UseCustomHeight(pIn))
827 {
828 // Note: if a custom slice align is present, it must be an even multiple
829 // of pitchForSlice, not just pitch.
830 UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / pOut->pitchForSlice;
831
832 if ((pIn->numSlices > 1) && (customizedHeight * elementBytes * pOut->pitchForSlice != pIn->sliceAlign))
833 {
834 returnCode = ADDR_INVALIDPARAMS;
835 }
836 else if ((pIn->numSlices > 1) && (pOut->height != customizedHeight))
837 {
838 returnCode = ADDR_INVALIDPARAMS;
839 }
840 else if ((pIn->height * elementBytes * pOut->pitch) > pIn->sliceAlign)
841 {
842 // If we only have one slice/depth, then we don't need an even multiple, but the slice size must still
843 // fit all the pixel data. The one provided is too small!
844 returnCode = ADDR_INVALIDPARAMS;
845 }
846 else
847 {
848 // For the single-slice case, the customized height could have been rounded down below the height since
849 // we allow non-multiples of pitch here, so take the max.
850 pOut->height = Max(pOut->height, customizedHeight);
851 }
852 }
853
854 return returnCode;
855 }
856
857 /**
858 ************************************************************************************************************************
859 * Lib::ComputeQbStereoInfo
860 *
861 * @brief
862 * Get quad buffer stereo information
863 * @return
864 * N/A
865 ************************************************************************************************************************
866 */
ComputeQbStereoInfo(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const867 VOID Lib::ComputeQbStereoInfo(
868 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] updated pOut+pStereoInfo
869 ) const
870 {
871 ADDR_ASSERT(pOut->bpp >= 8);
872 ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
873
874 // Save original height
875 pOut->pStereoInfo->eyeHeight = pOut->height;
876
877 // Right offset
878 pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
879
880 // Double height
881 pOut->height <<= 1;
882
883 ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
884
885 pOut->pixelHeight <<= 1;
886
887 // Double size
888 pOut->surfSize <<= 1;
889 pOut->sliceSize <<= 1;
890 }
891
892 } // V3
893 } // Addr
894