1 /*
2 ************************************************************************************************************************
3 *
4 * Copyright (C) 2007-2024 Advanced Micro Devices, Inc. All rights reserved.
5 * SPDX-License-Identifier: MIT
6 *
7 ***********************************************************************************************************************/
8
9
10 /**
11 ************************************************************************************************************************
12 * @file 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 < MaxNumMsaaRates; 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 = ComputeSurfaceInfoSanityCheck(&localIn);
282 }
283
284 if (returnCode == ADDR_OK)
285 {
286 returnCode = HwlComputeSurfaceInfo(&localIn, pOut);
287
288 if (returnCode == ADDR_OK)
289 {
290 pOut->bpp = localIn.bpp;
291 pOut->pixelPitch = pOut->pitch;
292 pOut->pixelHeight = pOut->height;
293
294 if (localIn.format != ADDR_FMT_INVALID)
295 {
296 UINT_32 pixelBits = pOut->pixelBits;
297
298 GetElemLib()->RestoreSurfaceInfo(elemMode,
299 expandX,
300 expandY,
301 &pOut->pixelBits,
302 &pOut->pixelPitch,
303 &pOut->pixelHeight);
304
305 GetElemLib()->RestoreSurfaceInfo(elemMode,
306 expandX,
307 expandY,
308 &pixelBits,
309 &pOut->pixelMipChainPitch,
310 &pOut->pixelMipChainHeight);
311
312 if ((localIn.numMipLevels > 1) && (pOut->pMipInfo != NULL))
313 {
314 for (UINT_32 i = 0; i < localIn.numMipLevels; i++)
315 {
316 pOut->pMipInfo[i].pixelPitch = pOut->pMipInfo[i].pitch;
317 pOut->pMipInfo[i].pixelHeight = pOut->pMipInfo[i].height;
318
319 GetElemLib()->RestoreSurfaceInfo(elemMode,
320 expandX,
321 expandY,
322 &pixelBits,
323 &pOut->pMipInfo[i].pixelPitch,
324 &pOut->pMipInfo[i].pixelHeight);
325 }
326 }
327
328 if (localIn.flags.qbStereo && (pOut->pStereoInfo != NULL))
329 {
330 ComputeQbStereoInfo(pOut);
331 }
332 }
333
334 SetEquationIndex(&localIn, pOut);
335 }
336 }
337
338 return returnCode;
339 }
340
341 /**
342 ************************************************************************************************************************
343 * Lib::GetPossibleSwizzleModes
344 *
345 * @brief
346 * Populates pOut with a list of the possible swizzle modes for the described surface.
347 *
348 * @return
349 * ADDR_E_RETURNCODE
350 ************************************************************************************************************************
351 */
GetPossibleSwizzleModes(const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT * pIn,ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT * pOut) const352 ADDR_E_RETURNCODE Lib::GetPossibleSwizzleModes(
353 const ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT* pIn,
354 ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT* pOut
355 ) const
356 {
357 ADDR_E_RETURNCODE returnCode = ADDR_OK;
358
359 if (GetFillSizeFieldsFlags() == TRUE)
360 {
361 if ((pIn->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT)) ||
362 (pOut->size != sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_OUTPUT)))
363 {
364 returnCode = ADDR_PARAMSIZEMISMATCH;
365 }
366 }
367
368 if ((returnCode == ADDR_OK) && (HwlValidateNonSwModeParams(pIn) == FALSE))
369 {
370 returnCode = ADDR_INVALIDPARAMS;
371 }
372
373 if (returnCode == ADDR_OK)
374 {
375 returnCode = HwlGetPossibleSwizzleModes(pIn, pOut);
376 }
377
378 return returnCode;
379 }
380
381 /**
382 ************************************************************************************************************************
383 * Lib::ComputeBlockDimensionForSurf
384 *
385 * @brief
386 * Internal function to get block width/height/depth in elements from surface input params.
387 *
388 * @return
389 * VOID
390 ************************************************************************************************************************
391 */
ComputeBlockDimensionForSurf(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,ADDR_EXTENT3D * pExtent) const392 VOID Lib::ComputeBlockDimensionForSurf(
393 const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
394 ADDR_EXTENT3D* pExtent
395 ) const
396 {
397 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pSurfInfo = pIn->pSurfInfo;
398 const UINT_32 log2BlkSize = GetBlockSizeLog2(pSurfInfo->swizzleMode);
399
400 HwlCalcBlockSize(pIn, pExtent);
401 }
402
403 /**
404 ************************************************************************************************************************
405 * Lib::GetMipTailDim
406 *
407 * @brief
408 * Internal function to get out max dimension of first level in mip tail
409 *
410 * @return
411 * Max Width/Height/Depth value of the first mip fitted in mip tail
412 ************************************************************************************************************************
413 */
GetMipTailDim(const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT * pIn,const ADDR_EXTENT3D & blockDims) const414 ADDR_EXTENT3D Lib::GetMipTailDim(
415 const ADDR3_COMPUTE_SURFACE_INFO_PARAMS_INPUT* pIn,
416 const ADDR_EXTENT3D& blockDims
417 ) const
418 {
419 return HwlGetMipInTailMaxSize(pIn, blockDims);
420 }
421
422 /**
423 ************************************************************************************************************************
424 * Lib::ComputeSurfaceAddrFromCoord
425 *
426 * @brief
427 * Interface function stub of ComputeSurfaceAddrFromCoord.
428 *
429 * @return
430 * ADDR_E_RETURNCODE
431 ************************************************************************************************************************
432 */
ComputeSurfaceAddrFromCoord(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const433 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
434 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
435 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
436 ) const
437 {
438 ADDR_E_RETURNCODE returnCode = ADDR_OK;
439
440 if (GetFillSizeFieldsFlags() == TRUE)
441 {
442 if ((pIn->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
443 (pOut->size != sizeof(ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
444 {
445 returnCode = ADDR_PARAMSIZEMISMATCH;
446 }
447 }
448
449 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
450 localIn.unAlignedDims.width = Max(pIn->unAlignedDims.width, 1u);
451 localIn.unAlignedDims.height = Max(pIn->unAlignedDims.height, 1u);
452 localIn.unAlignedDims.depth = Max(pIn->unAlignedDims.depth, 1u);
453 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
454 localIn.numSamples = Max(pIn->numSamples, 1u);
455
456 if ((localIn.bpp < 8) ||
457 (localIn.bpp > 128) ||
458 ((localIn.bpp % 8) != 0) ||
459 (localIn.sample >= localIn.numSamples) ||
460 (localIn.slice >= localIn.unAlignedDims.depth) ||
461 (localIn.mipId >= localIn.numMipLevels) ||
462 (IsTex3d(localIn.resourceType) &&
463 (Valid3DMipSliceIdConstraint(localIn.unAlignedDims.depth, localIn.mipId, localIn.slice) == FALSE)))
464 {
465 returnCode = ADDR_INVALIDPARAMS;
466 }
467
468 if (returnCode == ADDR_OK)
469 {
470 if (IsLinear(localIn.swizzleMode))
471 {
472 returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
473 }
474 else
475 {
476 returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
477 }
478
479 if (returnCode == ADDR_OK)
480 {
481 pOut->prtBlockIndex = static_cast<UINT_32>(pOut->addr / (64 * 1024));
482 }
483 }
484
485 return returnCode;
486 }
487
488 /**
489 ************************************************************************************************************************
490 * Lib::CopyLinearSurface
491 *
492 * @brief
493 * Implements uncompressed linear copies between memory and images.
494 *
495 * @return
496 * ADDR_E_RETURNCODE
497 ************************************************************************************************************************
498 */
CopyLinearSurface(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount,bool surfaceIsDst) const499 ADDR_E_RETURNCODE Lib::CopyLinearSurface(
500 const ADDR3_COPY_MEMSURFACE_INPUT* pIn,
501 const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
502 UINT_32 regionCount,
503 bool surfaceIsDst) const
504 {
505 ADDR3_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
506 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
507 ADDR3_MIP_INFO mipInfo[Addr3MaxMipLevels] = {{0}};
508 ADDR_ASSERT(pIn->numMipLevels <= Addr3MaxMipLevels);
509 ADDR_E_RETURNCODE returnCode = ADDR_OK;
510
511 if (pIn->numSamples > 1)
512 {
513 returnCode = ADDR_INVALIDPARAMS;
514 }
515
516 localIn.size = sizeof(localIn);
517 localIn.flags = pIn->flags;
518 localIn.swizzleMode = ADDR3_LINEAR;
519 localIn.resourceType = pIn->resourceType;
520 localIn.format = pIn->format;
521 localIn.bpp = pIn->bpp;
522 localIn.width = Max(pIn->unAlignedDims.width, 1u);
523 localIn.height = Max(pIn->unAlignedDims.height, 1u);
524 localIn.numSlices = Max(pIn->unAlignedDims.depth, 1u);
525 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
526 localIn.numSamples = Max(pIn->numSamples, 1u);
527
528 if (localIn.numMipLevels <= 1)
529 {
530 localIn.pitchInElement = pIn->pitchInElement;
531 }
532
533 localOut.size = sizeof(localOut);
534 localOut.pMipInfo = mipInfo;
535
536 if (returnCode == ADDR_OK)
537 {
538 returnCode = ComputeSurfaceInfo(&localIn, &localOut);
539 }
540
541 if (returnCode == ADDR_OK)
542 {
543 for (UINT_32 regionIdx = 0; regionIdx < regionCount; regionIdx++)
544 {
545 const ADDR3_COPY_MEMSURFACE_REGION* pCurRegion = &pRegions[regionIdx];
546
547 void* pMipBase = VoidPtrInc(pIn->pMappedSurface,
548 (pIn->singleSubres ? 0 : mipInfo[pCurRegion->mipId].offset));
549
550 const size_t lineSizeBytes = (localIn.bpp >> 3) * pCurRegion->copyDims.width;
551 const size_t lineImgPitchBytes = (localIn.bpp >> 3) * mipInfo[pCurRegion->mipId].pitch;
552
553 for (UINT_32 sliceIdx = 0; sliceIdx < pCurRegion->copyDims.depth; sliceIdx++)
554 {
555 UINT_32 sliceCoord = sliceIdx + pCurRegion->slice;
556 size_t imgOffsetInMip = (localOut.sliceSize * sliceCoord) +
557 (lineImgPitchBytes * pCurRegion->y) +
558 (pCurRegion->x * (pIn->bpp >> 3));
559 size_t memOffset = sliceIdx * pCurRegion->memSlicePitch;
560
561 for (UINT_32 yIdx = 0; yIdx < pCurRegion->copyDims.height; yIdx++)
562 {
563 if (surfaceIsDst)
564 {
565 memcpy(VoidPtrInc(pMipBase, imgOffsetInMip),
566 VoidPtrInc(pCurRegion->pMem, memOffset),
567 lineSizeBytes);
568 }
569 else
570 {
571 memcpy(VoidPtrInc(pCurRegion->pMem, memOffset),
572 VoidPtrInc(pMipBase, imgOffsetInMip),
573 lineSizeBytes);
574 }
575
576 imgOffsetInMip += lineImgPitchBytes;
577 memOffset += pCurRegion->memRowPitch;
578 }
579 }
580 }
581 }
582
583 return returnCode;
584 }
585
586 /**
587 ************************************************************************************************************************
588 * Lib::CopyMemToSurface
589 *
590 * @brief
591 * Interface function stub of Addr3CopyMemToSurface.
592 *
593 * @return
594 * ADDR_E_RETURNCODE
595 ************************************************************************************************************************
596 */
CopyMemToSurface(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount) const597 ADDR_E_RETURNCODE Lib::CopyMemToSurface(
598 const ADDR3_COPY_MEMSURFACE_INPUT* pIn,
599 const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
600 UINT_32 regionCount) const
601 {
602 ADDR_E_RETURNCODE returnCode = ADDR_OK;
603
604 if ((regionCount == 0) || (pRegions == NULL))
605 {
606 returnCode = ADDR_INVALIDPARAMS;
607 }
608 else if (GetFillSizeFieldsFlags() == TRUE)
609 {
610 if (pIn->size != sizeof(ADDR3_COPY_MEMSURFACE_INPUT))
611 {
612 returnCode = ADDR_INVALIDPARAMS;
613 }
614 else
615 {
616 UINT_32 baseSlice = pRegions[0].slice;
617 UINT_32 baseMip = pRegions[0].mipId;
618 BOOL_32 singleSubres = pIn->singleSubres;
619 for (UINT_32 i = 0; i < regionCount; i++)
620 {
621 if (pRegions[i].size != sizeof(ADDR3_COPY_MEMSURFACE_REGION))
622 {
623 returnCode = ADDR_INVALIDPARAMS;
624 break;
625 }
626 if (singleSubres &&
627 ((pRegions[i].copyDims.depth != 1) ||
628 (pRegions[i].slice != baseSlice) ||
629 (pRegions[i].mipId != baseMip)))
630 {
631 // Copy will cover multiple/interleaved subresources, a
632 // mapped pointer to a single subres cannot be valid.
633 returnCode = ADDR_INVALIDPARAMS;
634 break;
635 }
636 }
637 }
638 }
639
640 if (returnCode == ADDR_OK)
641 {
642 if (IsLinear(pIn->swizzleMode))
643 {
644 returnCode = CopyLinearSurface(pIn, pRegions, regionCount, true);
645 }
646 else
647 {
648 returnCode = HwlCopyMemToSurface(pIn, pRegions, regionCount);
649 }
650 }
651
652 return returnCode;
653 }
654
655 /**
656 ************************************************************************************************************************
657 * Lib::CopySurfaceToMem
658 *
659 * @brief
660 * Interface function stub of Addr3CopySurfaceToMem.
661 *
662 * @return
663 * ADDR_E_RETURNCODE
664 ************************************************************************************************************************
665 */
CopySurfaceToMem(const ADDR3_COPY_MEMSURFACE_INPUT * pIn,const ADDR3_COPY_MEMSURFACE_REGION * pRegions,UINT_32 regionCount) const666 ADDR_E_RETURNCODE Lib::CopySurfaceToMem(
667 const ADDR3_COPY_MEMSURFACE_INPUT* pIn,
668 const ADDR3_COPY_MEMSURFACE_REGION* pRegions,
669 UINT_32 regionCount) const
670 {
671 ADDR_E_RETURNCODE returnCode = ADDR_OK;
672
673 if (regionCount == 0)
674 {
675 returnCode = ADDR_INVALIDPARAMS;
676 }
677 else if (GetFillSizeFieldsFlags() == TRUE)
678 {
679 if (pIn->size != sizeof(ADDR3_COPY_MEMSURFACE_INPUT))
680 {
681 returnCode = ADDR_INVALIDPARAMS;
682 }
683 else
684 {
685 UINT_32 baseSlice = pRegions[0].slice;
686 UINT_32 baseMip = pRegions[0].mipId;
687 BOOL_32 singleSubres = pIn->singleSubres;
688 for (UINT_32 i = 0; i < regionCount; i++)
689 {
690 if (pRegions[i].size != sizeof(ADDR3_COPY_MEMSURFACE_REGION))
691 {
692 returnCode = ADDR_INVALIDPARAMS;
693 break;
694 }
695 if (singleSubres &&
696 ((pRegions[i].copyDims.depth != 1) ||
697 (pRegions[i].slice != baseSlice) ||
698 (pRegions[i].mipId != baseMip)))
699 {
700 // Copy will cover multiple/interleaved subresources, a
701 // mapped pointer to a single subres cannot be valid.
702 returnCode = ADDR_INVALIDPARAMS;
703 break;
704 }
705 }
706 }
707 }
708
709 if (returnCode == ADDR_OK)
710 {
711 if (IsLinear(pIn->swizzleMode))
712 {
713 returnCode = CopyLinearSurface(pIn, pRegions, regionCount, false);
714 }
715 else
716 {
717 returnCode = HwlCopySurfaceToMem(pIn, pRegions, regionCount);
718 }
719 }
720
721 return returnCode;
722 }
723
724 /**
725 ************************************************************************************************************************
726 * Lib::ComputeSurfaceAddrFromCoord
727 *
728 * @brief
729 * Interface function stub of Addr3ComputePipeBankXor.
730 *
731 * @return
732 * ADDR_E_RETURNCODE
733 ************************************************************************************************************************
734 */
ComputePipeBankXor(const ADDR3_COMPUTE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT * pOut)735 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
736 const ADDR3_COMPUTE_PIPEBANKXOR_INPUT* pIn,
737 ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT* pOut)
738 {
739 ADDR_E_RETURNCODE returnCode;
740
741 if ((GetFillSizeFieldsFlags() == TRUE) &&
742 ((pIn->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_INPUT)) ||
743 (pOut->size != sizeof(ADDR3_COMPUTE_PIPEBANKXOR_OUTPUT))))
744 {
745 returnCode = ADDR_INVALIDPARAMS;
746 }
747 else
748 {
749 returnCode = HwlComputePipeBankXor(pIn, pOut);
750 }
751
752 return returnCode;
753 }
754
755 /**
756 ************************************************************************************************************************
757 * Lib::ComputeSurfaceAddrFromCoordLinear
758 *
759 * @brief
760 * Internal function to calculate address from coord for linear swizzle surface
761 *
762 * @return
763 * ADDR_E_RETURNCODE
764 ************************************************************************************************************************
765 */
ComputeSurfaceAddrFromCoordLinear(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const766 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
767 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
768 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
769 ) const
770 {
771 ADDR_E_RETURNCODE returnCode = ADDR_OK;
772 BOOL_32 valid = (pIn->numSamples <= 1);
773
774 if (valid)
775 {
776 if (IsTex1d(pIn->resourceType))
777 {
778 valid = (pIn->y == 0);
779 }
780 }
781
782 if (valid)
783 {
784 ADDR3_COMPUTE_SURFACE_INFO_INPUT surfInfoIn = {0};
785
786 surfInfoIn.size = sizeof(surfInfoIn);
787 surfInfoIn.flags = pIn->flags;
788 surfInfoIn.swizzleMode = ADDR3_LINEAR;
789 surfInfoIn.resourceType = pIn->resourceType;
790 surfInfoIn.format = ADDR_FMT_INVALID;
791 surfInfoIn.bpp = pIn->bpp;
792 surfInfoIn.width = Max(pIn->unAlignedDims.width, 1u);
793 surfInfoIn.height = Max(pIn->unAlignedDims.height, 1u);
794 surfInfoIn.numSlices = Max(pIn->unAlignedDims.depth, 1u);
795 surfInfoIn.numMipLevels = Max(pIn->numMipLevels, 1u);
796 surfInfoIn.numSamples = Max(pIn->numSamples, 1u);
797
798 if (surfInfoIn.numMipLevels <= 1)
799 {
800 surfInfoIn.pitchInElement = pIn->pitchInElement;
801 }
802
803 returnCode = HwlComputeSurfaceAddrFromCoordLinear(pIn, &surfInfoIn, pOut);
804 }
805
806 if (valid == FALSE)
807 {
808 returnCode = ADDR_INVALIDPARAMS;
809 }
810
811 return returnCode;
812 }
813
814 /**
815 ************************************************************************************************************************
816 * Lib::ComputeSurfaceAddrFromCoordTiled
817 *
818 * @brief
819 * Internal function to calculate address from coord for tiled swizzle surface
820 *
821 * @return
822 * ADDR_E_RETURNCODE
823 ************************************************************************************************************************
824 */
ComputeSurfaceAddrFromCoordTiled(const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT * pIn,ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT * pOut) const825 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
826 const ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
827 ADDR3_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
828 ) const
829 {
830 return HwlComputeSurfaceAddrFromCoordTiled(pIn, pOut);
831 }
832
833 /**
834 ************************************************************************************************************************
835 * Lib::ComputeNonBlockCompressedView
836 *
837 * @brief
838 * Interface function stub of Addr3ComputeNonBlockCompressedView.
839 *
840 * @return
841 * ADDR_E_RETURNCODE
842 ************************************************************************************************************************
843 */
ComputeNonBlockCompressedView(const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT * pIn,ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT * pOut)844 ADDR_E_RETURNCODE Lib::ComputeNonBlockCompressedView(
845 const ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT* pIn,
846 ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT* pOut)
847 {
848 ADDR_E_RETURNCODE returnCode;
849
850 if ((GetFillSizeFieldsFlags() == TRUE) &&
851 ((pIn->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_INPUT)) ||
852 (pOut->size != sizeof(ADDR3_COMPUTE_NONBLOCKCOMPRESSEDVIEW_OUTPUT))))
853 {
854 returnCode = ADDR_INVALIDPARAMS;
855 }
856 else if (Is3dSwizzle(pIn->swizzleMode))
857 {
858 // 3D volume images using ADDR3_XX_3D is currently not supported.
859 returnCode = ADDR_NOTSUPPORTED;
860 }
861 else
862 {
863 returnCode = HwlComputeNonBlockCompressedView(pIn, pOut);
864 }
865
866 return returnCode;
867 }
868
869 /**
870 ************************************************************************************************************************
871 * Lib::ComputeSubResourceOffsetForSwizzlePattern
872 *
873 * @brief
874 * Interface function stub of Addr3ComputeSubResourceOffsetForSwizzlePattern.
875 *
876 * @return
877 * ADDR_E_RETURNCODE
878 ************************************************************************************************************************
879 */
ComputeSubResourceOffsetForSwizzlePattern(const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT * pIn,ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT * pOut)880 ADDR_E_RETURNCODE Lib::ComputeSubResourceOffsetForSwizzlePattern(
881 const ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT* pIn,
882 ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT* pOut)
883 {
884 ADDR_E_RETURNCODE returnCode = ADDR_OK;
885
886 if ((GetFillSizeFieldsFlags() == TRUE) &&
887 ((pIn->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_INPUT)) ||
888 (pOut->size != sizeof(ADDR3_COMPUTE_SUBRESOURCE_OFFSET_FORSWIZZLEPATTERN_OUTPUT))))
889 {
890 returnCode = ADDR_INVALIDPARAMS;
891 }
892 else
893 {
894 HwlComputeSubResourceOffsetForSwizzlePattern(pIn, pOut);
895 }
896
897 return returnCode;
898 }
899
900 /**
901 ************************************************************************************************************************
902 * Lib::ComputeSlicePipeBankXor
903 *
904 * @brief
905 * Interface function stub of Addr3ComputeSlicePipeBankXor.
906 *
907 * @return
908 * ADDR_E_RETURNCODE
909 ************************************************************************************************************************
910 */
ComputeSlicePipeBankXor(const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT * pIn,ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT * pOut)911 ADDR_E_RETURNCODE Lib::ComputeSlicePipeBankXor(
912 const ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT* pIn,
913 ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT* pOut)
914 {
915 ADDR_E_RETURNCODE returnCode;
916
917 if ((GetFillSizeFieldsFlags() == TRUE) &&
918 ((pIn->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_INPUT)) ||
919 (pOut->size != sizeof(ADDR3_COMPUTE_SLICE_PIPEBANKXOR_OUTPUT))))
920 {
921 returnCode = ADDR_INVALIDPARAMS;
922 }
923 if ((pIn->bpe != 0) &&
924 (pIn->bpe != 8) &&
925 (pIn->bpe != 16) &&
926 (pIn->bpe != 32) &&
927 (pIn->bpe != 64) &&
928 (pIn->bpe != 128))
929 {
930 returnCode = ADDR_INVALIDPARAMS;
931 }
932 else
933 {
934 returnCode = HwlComputeSlicePipeBankXor(pIn, pOut);
935 }
936
937 return returnCode;
938 }
939
940 /**
941 ************************************************************************************************************************
942 * Lib::UseCustomHeight
943 *
944 * @brief
945 * Determines if the calculations for this surface should use minimal HW values or user-specified values.
946 *
947 * @return
948 * Returns TRUE if the user-specified alignment should be used
949 ************************************************************************************************************************
950 */
UseCustomHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const951 BOOL_32 Lib::UseCustomHeight(
952 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
953 ) const
954 {
955 return ((pIn->numMipLevels <= 1) &&
956 IsLinear(pIn->swizzleMode) &&
957 (pIn->sliceAlign > 0));
958 }
959
960 /**
961 ************************************************************************************************************************
962 * Lib::UseCustomPitch
963 *
964 * @brief
965 * Determines if the calculations for this surface should use minimal HW values or user-specified values.
966 *
967 * @return
968 * Returns TRUE if the user-specified pitch should be used
969 ************************************************************************************************************************
970 */
UseCustomPitch(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const971 BOOL_32 Lib::UseCustomPitch(
972 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
973 ) const
974 {
975 return ((pIn->numMipLevels <= 1) &&
976 IsLinear(pIn->swizzleMode) &&
977 (pIn->pitchInElement > 0));
978 }
979
980 /**
981 ************************************************************************************************************************
982 * Lib::CanTrimLinearPadding
983 *
984 * @brief
985 * Determines if the calculations for this surface can omit extra trailing padding for linear surfaces.
986 *
987 * @return
988 * Returns TRUE if the trailing padding can be omitted.
989 ************************************************************************************************************************
990 */
CanTrimLinearPadding(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const991 BOOL_32 Lib::CanTrimLinearPadding(
992 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn
993 ) const
994 {
995 return ((IsTex3d(pIn->resourceType) == FALSE) &&
996 (pIn->numSlices <= 1) &&
997 IsLinear(pIn->swizzleMode));
998 }
999
1000 /**
1001 ************************************************************************************************************************
1002 * Lib::ApplyCustomizedPitchHeight
1003 *
1004 * @brief
1005 * Helper function to override hw required row pitch/slice pitch by customrized one
1006 *
1007 * @return
1008 * ADDR_E_RETURNCODE
1009 ************************************************************************************************************************
1010 */
ApplyCustomizedPitchHeight(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn,ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1011 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
1012 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1013 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut
1014 ) const
1015 {
1016 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1017
1018 const UINT_32 elementBytes = pIn->bpp >> 3;
1019
1020 UINT_32 pitchAlignmentElements = pOut->blockExtent.width;
1021 UINT_32 pitchSliceAlignmentElements = pOut->blockExtent.width;
1022
1023 if (IsLinear(pIn->swizzleMode))
1024 {
1025 // Normal pitch of image data
1026 const UINT_32 pitchAlignmentBytes = 1 << GetBlockSizeLog2(pIn->swizzleMode, TRUE);
1027 pitchAlignmentElements = pitchAlignmentBytes / elementBytes;
1028
1029 // Pitch of image data used for slice sizing
1030 const UINT_32 pitchSliceAlignmentBytes = 1 << GetBlockSizeLog2(pIn->swizzleMode, CanTrimLinearPadding(pIn));
1031 pitchSliceAlignmentElements = pitchSliceAlignmentBytes / elementBytes;
1032 }
1033
1034 pOut->pitch = PowTwoAlign(pIn->width, pitchAlignmentElements);
1035 pOut->pitchForSlice = PowTwoAlign(pIn->width, pitchSliceAlignmentElements);
1036
1037 UINT_32 heightAlign = pOut->blockExtent.height;
1038
1039 if (pIn->flags.qbStereo)
1040 {
1041 UINT_32 rightXor = 0;
1042
1043 returnCode = HwlComputeStereoInfo(pIn, &heightAlign, &rightXor);
1044
1045 if (returnCode == ADDR_OK)
1046 {
1047 pOut->pStereoInfo->rightSwizzle = rightXor;
1048 }
1049 }
1050
1051 pOut->height = PowTwoAlign(pIn->height, heightAlign);
1052
1053 // Custom pitches / alignments are only possible with single mip level / linear images; otherwise,
1054 // ignore those parameters.
1055 if ((returnCode == ADDR_OK) && UseCustomPitch(pIn))
1056 {
1057 // Their requested pitch has to meet the pitch alignment constraints applied by the HW.
1058 if ((pIn->pitchInElement % pitchAlignmentElements) != 0)
1059 {
1060 returnCode = ADDR_INVALIDPARAMS;
1061 }
1062 // And their pitch can't be less than the minimum
1063 else if (pIn->pitchInElement < pOut->pitch)
1064 {
1065 returnCode = ADDR_INVALIDPARAMS;
1066 }
1067 else
1068 {
1069 pOut->pitch = pIn->pitchInElement;
1070 pOut->pitchForSlice = PowTwoAlign(pIn->pitchInElement, pitchSliceAlignmentElements);
1071 }
1072 }
1073
1074 if ((returnCode == ADDR_OK) && UseCustomHeight(pIn))
1075 {
1076 // Note: if a custom slice align is present, it must be an even multiple
1077 // of pitchForSlice, not just pitch.
1078 UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / pOut->pitchForSlice;
1079
1080 if ((pIn->numSlices > 1) && (customizedHeight * elementBytes * pOut->pitchForSlice != pIn->sliceAlign))
1081 {
1082 returnCode = ADDR_INVALIDPARAMS;
1083 }
1084 else if ((pIn->numSlices > 1) && (pOut->height != customizedHeight))
1085 {
1086 returnCode = ADDR_INVALIDPARAMS;
1087 }
1088 else if ((pIn->height * elementBytes * pOut->pitch) > pIn->sliceAlign)
1089 {
1090 // If we only have one slice/depth, then we don't need an even multiple, but the slice size must still
1091 // fit all the pixel data. The one provided is too small!
1092 returnCode = ADDR_INVALIDPARAMS;
1093 }
1094 else
1095 {
1096 // For the single-slice case, the customized height could have been rounded down below the height since
1097 // we allow non-multiples of pitch here, so take the max.
1098 pOut->height = Max(pOut->height, customizedHeight);
1099 }
1100 }
1101
1102 return returnCode;
1103 }
1104
1105
1106 /**
1107 ************************************************************************************************************************
1108 * Lib::ComputeQbStereoInfo
1109 *
1110 * @brief
1111 * Get quad buffer stereo information
1112 * @return
1113 * N/A
1114 ************************************************************************************************************************
1115 */
ComputeQbStereoInfo(ADDR3_COMPUTE_SURFACE_INFO_OUTPUT * pOut) const1116 VOID Lib::ComputeQbStereoInfo(
1117 ADDR3_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [in,out] updated pOut+pStereoInfo
1118 ) const
1119 {
1120 ADDR_ASSERT(pOut->bpp >= 8);
1121 ADDR_ASSERT((pOut->surfSize % pOut->baseAlign) == 0);
1122
1123 // Save original height
1124 pOut->pStereoInfo->eyeHeight = pOut->height;
1125
1126 // Right offset
1127 pOut->pStereoInfo->rightOffset = static_cast<UINT_32>(pOut->surfSize);
1128
1129 // Double height
1130 pOut->height <<= 1;
1131
1132 ADDR_ASSERT(pOut->height <= MaxSurfaceHeight);
1133
1134 pOut->pixelHeight <<= 1;
1135
1136 // Double size
1137 pOut->surfSize <<= 1;
1138 pOut->sliceSize <<= 1;
1139 }
1140
1141 /**
1142 ************************************************************************************************************************
1143 * Lib::ComputeSurfaceInfoSanityCheck
1144 *
1145 * @brief
1146 * Internal function to do basic sanity check before compute surface info
1147 *
1148 * @return
1149 * ADDR_E_RETURNCODE
1150 ************************************************************************************************************************
1151 */
ComputeSurfaceInfoSanityCheck(const ADDR3_COMPUTE_SURFACE_INFO_INPUT * pIn) const1152 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoSanityCheck(
1153 const ADDR3_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in] input structure
1154 ) const
1155 {
1156 ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT localIn = {};
1157 localIn.size = sizeof(ADDR3_GET_POSSIBLE_SWIZZLE_MODE_INPUT);
1158 localIn.flags = pIn->flags;
1159 localIn.resourceType = pIn->resourceType;
1160 localIn.bpp = pIn->bpp;
1161 localIn.width = pIn->width;
1162 localIn.height = pIn->height;
1163 localIn.numSlices = pIn->numSlices;
1164 localIn.numMipLevels = pIn->numMipLevels;
1165 localIn.numSamples = pIn->numSamples;
1166
1167 return HwlValidateNonSwModeParams(&localIn) ? ADDR_OK : ADDR_INVALIDPARAMS;
1168 }
1169
1170 } // V3
1171 } // Addr
1172