gallium/util: move endian detect into a separate file
[mesa.git] / src / gallium / winsys / amdgpu / drm / addrlib / r800 / egbaddrlib.cpp
1 /*
2 * Copyright © 2014 Advanced Micro Devices, Inc.
3 * All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
14 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
15 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16 * NON-INFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS, AUTHORS
17 * AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
20 * USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * The above copyright notice and this permission notice (including the
23 * next paragraph) shall be included in all copies or substantial portions
24 * of the Software.
25 */
26
27 /**
28 ***************************************************************************************************
29 * @file egbaddrlib.cpp
30 * @brief Contains the EgBasedAddrLib class implementation
31 ***************************************************************************************************
32 */
33
34 #include "egbaddrlib.h"
35
36 /**
37 ***************************************************************************************************
38 * EgBasedAddrLib::EgBasedAddrLib
39 *
40 * @brief
41 * Constructor
42 *
43 * @note
44 *
45 ***************************************************************************************************
46 */
47 EgBasedAddrLib::EgBasedAddrLib(const AddrClient* pClient) :
48 AddrLib(pClient),
49 m_ranks(0),
50 m_logicalBanks(0),
51 m_bankInterleave(1)
52 {
53 }
54
55 /**
56 ***************************************************************************************************
57 * EgBasedAddrLib::~EgBasedAddrLib
58 *
59 * @brief
60 * Destructor
61 ***************************************************************************************************
62 */
63 EgBasedAddrLib::~EgBasedAddrLib()
64 {
65 }
66
67 /**
68 ***************************************************************************************************
69 * EgBasedAddrLib::DispatchComputeSurfaceInfo
70 *
71 * @brief
72 * Compute surface sizes include padded pitch,height,slices,total size in bytes,
73 * meanwhile output suitable tile mode and base alignment might be changed in this
74 * call as well. Results are returned through output parameters.
75 *
76 * @return
77 * TRUE if no error occurs
78 ***************************************************************************************************
79 */
80 BOOL_32 EgBasedAddrLib::DispatchComputeSurfaceInfo(
81 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
82 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
83 ) const
84 {
85 AddrTileMode tileMode = pIn->tileMode;
86 UINT_32 bpp = pIn->bpp;
87 UINT_32 numSamples = pIn->numSamples;
88 UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
89 UINT_32 pitch = pIn->width;
90 UINT_32 height = pIn->height;
91 UINT_32 numSlices = pIn->numSlices;
92 UINT_32 mipLevel = pIn->mipLevel;
93 ADDR_SURFACE_FLAGS flags = pIn->flags;
94
95 ADDR_TILEINFO tileInfoDef = {0};
96 ADDR_TILEINFO* pTileInfo = &tileInfoDef;
97
98 UINT_32 padDims = 0;
99 BOOL_32 valid;
100
101 tileMode = DegradeLargeThickTile(tileMode, bpp);
102
103 // Only override numSamples for NI above
104 if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
105 {
106 if (numFrags != numSamples) // This means EQAA
107 {
108 // The real surface size needed is determined by number of fragments
109 numSamples = numFrags;
110 }
111
112 // Save altered numSamples in pOut
113 pOut->numSamples = numSamples;
114 }
115
116 // Caller makes sure pOut->pTileInfo is not NULL, see HwlComputeSurfaceInfo
117 ADDR_ASSERT(pOut->pTileInfo);
118
119 if (pOut->pTileInfo != NULL)
120 {
121 pTileInfo = pOut->pTileInfo;
122 }
123
124 // Set default values
125 if (pIn->pTileInfo != NULL)
126 {
127 if (pTileInfo != pIn->pTileInfo)
128 {
129 *pTileInfo = *pIn->pTileInfo;
130 }
131 }
132 else
133 {
134 memset(pTileInfo, 0, sizeof(ADDR_TILEINFO));
135 }
136
137 // For macro tile mode, we should calculate default tiling parameters
138 HwlSetupTileInfo(tileMode,
139 flags,
140 bpp,
141 pitch,
142 height,
143 numSamples,
144 pIn->pTileInfo,
145 pTileInfo,
146 pIn->tileType,
147 pOut);
148
149 if (flags.cube)
150 {
151 if (mipLevel == 0)
152 {
153 padDims = 2;
154 }
155
156 if (numSlices == 1)
157 {
158 // This is calculating one face, remove cube flag
159 flags.cube = 0;
160 }
161 }
162
163 switch (tileMode)
164 {
165 case ADDR_TM_LINEAR_GENERAL://fall through
166 case ADDR_TM_LINEAR_ALIGNED:
167 valid = ComputeSurfaceInfoLinear(pIn, pOut, padDims);
168 break;
169
170 case ADDR_TM_1D_TILED_THIN1://fall through
171 case ADDR_TM_1D_TILED_THICK:
172 valid = ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, tileMode);
173 break;
174
175 case ADDR_TM_2D_TILED_THIN1: //fall through
176 case ADDR_TM_2D_TILED_THICK: //fall through
177 case ADDR_TM_3D_TILED_THIN1: //fall through
178 case ADDR_TM_3D_TILED_THICK: //fall through
179 case ADDR_TM_2D_TILED_XTHICK: //fall through
180 case ADDR_TM_3D_TILED_XTHICK: //fall through
181 case ADDR_TM_PRT_TILED_THIN1: //fall through
182 case ADDR_TM_PRT_2D_TILED_THIN1://fall through
183 case ADDR_TM_PRT_3D_TILED_THIN1://fall through
184 case ADDR_TM_PRT_TILED_THICK: //fall through
185 case ADDR_TM_PRT_2D_TILED_THICK://fall through
186 case ADDR_TM_PRT_3D_TILED_THICK:
187 valid = ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, tileMode);
188 break;
189
190 default:
191 valid = FALSE;
192 ADDR_ASSERT_ALWAYS();
193 break;
194 }
195
196 return valid;
197 }
198
199 /**
200 ***************************************************************************************************
201 * EgBasedAddrLib::ComputeSurfaceInfoLinear
202 *
203 * @brief
204 * Compute linear surface sizes include padded pitch, height, slices, total size in
205 * bytes, meanwhile alignments as well. Since it is linear mode, so output tile mode
206 * will not be changed here. Results are returned through output parameters.
207 *
208 * @return
209 * TRUE if no error occurs
210 ***************************************************************************************************
211 */
212 BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoLinear(
213 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
214 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
215 UINT_32 padDims ///< [in] Dimensions to padd
216 ) const
217 {
218 UINT_32 expPitch = pIn->width;
219 UINT_32 expHeight = pIn->height;
220 UINT_32 expNumSlices = pIn->numSlices;
221
222 // No linear MSAA on real H/W, keep this for TGL
223 UINT_32 numSamples = pOut->numSamples;
224
225 const UINT_32 microTileThickness = 1;
226
227 //
228 // Compute the surface alignments.
229 //
230 ComputeSurfaceAlignmentsLinear(pIn->tileMode,
231 pIn->bpp,
232 pIn->flags,
233 &pOut->baseAlign,
234 &pOut->pitchAlign,
235 &pOut->heightAlign);
236
237 if ((pIn->tileMode == ADDR_TM_LINEAR_GENERAL) && pIn->flags.color && (pIn->height > 1))
238 {
239 #if !ALT_TEST
240 // When linear_general surface is accessed in multiple lines, it requires 8 pixels in pitch
241 // alignment since PITCH_TILE_MAX is in unit of 8 pixels.
242 // It is OK if it is accessed per line.
243 ADDR_ASSERT((pIn->width % 8) == 0);
244 #endif
245 }
246
247 pOut->depthAlign = microTileThickness;
248
249 expPitch = HwlPreHandleBaseLvl3xPitch(pIn, expPitch);
250
251 //
252 // Pad pitch and height to the required granularities.
253 //
254 PadDimensions(pIn->tileMode,
255 pIn->bpp,
256 pIn->flags,
257 numSamples,
258 pOut->pTileInfo,
259 padDims,
260 pIn->mipLevel,
261 &expPitch, pOut->pitchAlign,
262 &expHeight, pOut->heightAlign,
263 &expNumSlices, microTileThickness);
264
265 expPitch = HwlPostHandleBaseLvl3xPitch(pIn, expPitch);
266
267 //
268 // Adjust per HWL
269 //
270
271 UINT_64 logicalSliceSize;
272
273 logicalSliceSize = HwlGetSizeAdjustmentLinear(pIn->tileMode,
274 pIn->bpp,
275 numSamples,
276 pOut->baseAlign,
277 pOut->pitchAlign,
278 &expPitch,
279 &expHeight,
280 &pOut->heightAlign);
281
282
283 pOut->pitch = expPitch;
284 pOut->height = expHeight;
285 pOut->depth = expNumSlices;
286
287 pOut->surfSize = logicalSliceSize * expNumSlices;
288
289 pOut->tileMode = pIn->tileMode;
290
291 return TRUE;
292 }
293
294 /**
295 ***************************************************************************************************
296 * EgBasedAddrLib::ComputeSurfaceInfoMicroTiled
297 *
298 * @brief
299 * Compute 1D/Micro Tiled surface sizes include padded pitch, height, slices, total
300 * size in bytes, meanwhile alignments as well. Results are returned through output
301 * parameters.
302 *
303 * @return
304 * TRUE if no error occurs
305 ***************************************************************************************************
306 */
307 BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMicroTiled(
308 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
309 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
310 UINT_32 padDims, ///< [in] Dimensions to padd
311 AddrTileMode expTileMode ///< [in] Expected tile mode
312 ) const
313 {
314 BOOL_32 valid = TRUE;
315
316 UINT_32 microTileThickness;
317 UINT_32 expPitch = pIn->width;
318 UINT_32 expHeight = pIn->height;
319 UINT_32 expNumSlices = pIn->numSlices;
320
321 // No 1D MSAA on real H/W, keep this for TGL
322 UINT_32 numSamples = pOut->numSamples;
323
324 //
325 // Compute the micro tile thickness.
326 //
327 microTileThickness = ComputeSurfaceThickness(expTileMode);
328
329 //
330 // Extra override for mip levels
331 //
332 if (pIn->mipLevel > 0)
333 {
334 //
335 // Reduce tiling mode from thick to thin if the number of slices is less than the
336 // micro tile thickness.
337 //
338 if ((expTileMode == ADDR_TM_1D_TILED_THICK) &&
339 (expNumSlices < ThickTileThickness))
340 {
341 expTileMode = HwlDegradeThickTileMode(ADDR_TM_1D_TILED_THICK, expNumSlices, NULL);
342 if (expTileMode != ADDR_TM_1D_TILED_THICK)
343 {
344 microTileThickness = 1;
345 }
346 }
347 }
348
349 //
350 // Compute the surface restrictions.
351 //
352 ComputeSurfaceAlignmentsMicroTiled(expTileMode,
353 pIn->bpp,
354 pIn->flags,
355 pIn->mipLevel,
356 numSamples,
357 &pOut->baseAlign,
358 &pOut->pitchAlign,
359 &pOut->heightAlign);
360
361 pOut->depthAlign = microTileThickness;
362
363 //
364 // Pad pitch and height to the required granularities.
365 // Compute surface size.
366 // Return parameters.
367 //
368 PadDimensions(expTileMode,
369 pIn->bpp,
370 pIn->flags,
371 numSamples,
372 pOut->pTileInfo,
373 padDims,
374 pIn->mipLevel,
375 &expPitch, pOut->pitchAlign,
376 &expHeight, pOut->heightAlign,
377 &expNumSlices, microTileThickness);
378
379 //
380 // Get HWL specific pitch adjustment
381 //
382 UINT_64 logicalSliceSize = HwlGetSizeAdjustmentMicroTiled(microTileThickness,
383 pIn->bpp,
384 pIn->flags,
385 numSamples,
386 pOut->baseAlign,
387 pOut->pitchAlign,
388 &expPitch,
389 &expHeight);
390
391
392 pOut->pitch = expPitch;
393 pOut->height = expHeight;
394 pOut->depth = expNumSlices;
395
396 pOut->surfSize = logicalSliceSize * expNumSlices;
397
398 pOut->tileMode = expTileMode;
399
400 return valid;
401 }
402
403
404 /**
405 ***************************************************************************************************
406 * EgBasedAddrLib::ComputeSurfaceInfoMacroTiled
407 *
408 * @brief
409 * Compute 2D/macro tiled surface sizes include padded pitch, height, slices, total
410 * size in bytes, meanwhile output suitable tile mode and alignments might be changed
411 * in this call as well. Results are returned through output parameters.
412 *
413 * @return
414 * TRUE if no error occurs
415 ***************************************************************************************************
416 */
417 BOOL_32 EgBasedAddrLib::ComputeSurfaceInfoMacroTiled(
418 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] Input structure
419 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut, ///< [out] Output structure
420 UINT_32 padDims, ///< [in] Dimensions to padd
421 AddrTileMode expTileMode ///< [in] Expected tile mode
422 ) const
423 {
424 BOOL_32 valid = TRUE;
425
426 AddrTileMode origTileMode = expTileMode;
427 UINT_32 microTileThickness;
428
429 UINT_32 paddedPitch;
430 UINT_32 paddedHeight;
431 UINT_64 bytesPerSlice;
432
433 UINT_32 expPitch = pIn->width;
434 UINT_32 expHeight = pIn->height;
435 UINT_32 expNumSlices = pIn->numSlices;
436
437 UINT_32 numSamples = pOut->numSamples;
438
439 //
440 // Compute the surface restrictions as base
441 // SanityCheckMacroTiled is called in ComputeSurfaceAlignmentsMacroTiled
442 //
443 valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode,
444 pIn->bpp,
445 pIn->flags,
446 pIn->mipLevel,
447 numSamples,
448 pOut->pTileInfo,
449 &pOut->baseAlign,
450 &pOut->pitchAlign,
451 &pOut->heightAlign);
452
453 if (valid)
454 {
455 //
456 // Compute the micro tile thickness.
457 //
458 microTileThickness = ComputeSurfaceThickness(expTileMode);
459
460 //
461 // Find the correct tiling mode for mip levels
462 //
463 if (pIn->mipLevel > 0)
464 {
465 //
466 // Try valid tile mode
467 //
468 expTileMode = ComputeSurfaceMipLevelTileMode(expTileMode,
469 pIn->bpp,
470 expPitch,
471 expHeight,
472 expNumSlices,
473 numSamples,
474 pOut->pitchAlign,
475 pOut->heightAlign,
476 pOut->pTileInfo);
477
478 if (!IsMacroTiled(expTileMode)) // Downgraded to micro-tiled
479 {
480 return ComputeSurfaceInfoMicroTiled(pIn, pOut, padDims, expTileMode);
481 }
482 else
483 {
484 if (microTileThickness != ComputeSurfaceThickness(expTileMode))
485 {
486 //
487 // Re-compute if thickness changed since bank-height may be changed!
488 //
489 return ComputeSurfaceInfoMacroTiled(pIn, pOut, padDims, expTileMode);
490 }
491 }
492 }
493
494 paddedPitch = expPitch;
495 paddedHeight = expHeight;
496
497 //
498 // Re-cal alignment
499 //
500 if (expTileMode != origTileMode) // Tile mode is changed but still macro-tiled
501 {
502 valid = ComputeSurfaceAlignmentsMacroTiled(expTileMode,
503 pIn->bpp,
504 pIn->flags,
505 pIn->mipLevel,
506 numSamples,
507 pOut->pTileInfo,
508 &pOut->baseAlign,
509 &pOut->pitchAlign,
510 &pOut->heightAlign);
511 }
512
513 //
514 // Do padding
515 //
516 PadDimensions(expTileMode,
517 pIn->bpp,
518 pIn->flags,
519 numSamples,
520 pOut->pTileInfo,
521 padDims,
522 pIn->mipLevel,
523 &paddedPitch, pOut->pitchAlign,
524 &paddedHeight, pOut->heightAlign,
525 &expNumSlices, microTileThickness);
526
527 if (pIn->flags.qbStereo &&
528 (pOut->pStereoInfo != NULL) &&
529 HwlStereoCheckRightOffsetPadding())
530 {
531 // Eye height's bank bits are different from y == 0?
532 // Since 3D rendering treats right eye buffer starting from y == "eye height" while
533 // display engine treats it to be 0, so the bank bits may be different, we pad
534 // more in height to make sure y == "eye height" has the same bank bits as y == 0.
535 UINT_32 checkMask = pOut->pTileInfo->banks - 1;
536 UINT_32 bankBits = 0;
537 do
538 {
539 bankBits = (paddedHeight / 8 / pOut->pTileInfo->bankHeight) & checkMask;
540
541 if (bankBits)
542 {
543 paddedHeight += pOut->heightAlign;
544 }
545 } while (bankBits);
546 }
547
548 //
549 // Compute the size of a slice.
550 //
551 bytesPerSlice = BITS_TO_BYTES(static_cast<UINT_64>(paddedPitch) *
552 paddedHeight * NextPow2(pIn->bpp) * numSamples);
553
554 pOut->pitch = paddedPitch;
555 // Put this check right here to workaround special mipmap cases which the original height
556 // is needed.
557 // The original height is pre-stored in pOut->height in PostComputeMipLevel and
558 // pOut->pitch is needed in HwlCheckLastMacroTiledLvl, too.
559 if (m_configFlags.checkLast2DLevel && numSamples == 1) // Don't check MSAA
560 {
561 // Set a TRUE in pOut if next Level is the first 1D sub level
562 HwlCheckLastMacroTiledLvl(pIn, pOut);
563 }
564 pOut->height = paddedHeight;
565
566 pOut->depth = expNumSlices;
567
568 pOut->surfSize = bytesPerSlice * expNumSlices;
569
570 pOut->tileMode = expTileMode;
571
572 pOut->depthAlign = microTileThickness;
573
574 } // if (valid)
575
576 return valid;
577 }
578
579 /**
580 ***************************************************************************************************
581 * EgBasedAddrLib::ComputeSurfaceAlignmentsLinear
582 *
583 * @brief
584 * Compute linear surface alignment, calculation results are returned through
585 * output parameters.
586 *
587 * @return
588 * TRUE if no error occurs
589 ***************************************************************************************************
590 */
591 BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsLinear(
592 AddrTileMode tileMode, ///< [in] tile mode
593 UINT_32 bpp, ///< [in] bits per pixel
594 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
595 UINT_32* pBaseAlign, ///< [out] base address alignment in bytes
596 UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels
597 UINT_32* pHeightAlign ///< [out] height alignment in pixels
598 ) const
599 {
600 BOOL_32 valid = TRUE;
601
602 switch (tileMode)
603 {
604 case ADDR_TM_LINEAR_GENERAL:
605 //
606 // The required base alignment and pitch and height granularities is to 1 element.
607 //
608 *pBaseAlign = (bpp > 8) ? bpp / 8 : 1;
609 *pPitchAlign = 1;
610 *pHeightAlign = 1;
611 break;
612 case ADDR_TM_LINEAR_ALIGNED:
613 //
614 // The required alignment for base is the pipe interleave size.
615 // The required granularity for pitch is hwl dependent.
616 // The required granularity for height is one row.
617 //
618 *pBaseAlign = m_pipeInterleaveBytes;
619 *pPitchAlign = HwlGetPitchAlignmentLinear(bpp, flags);
620 *pHeightAlign = 1;
621 break;
622 default:
623 *pBaseAlign = 1;
624 *pPitchAlign = 1;
625 *pHeightAlign = 1;
626 ADDR_UNHANDLED_CASE();
627 break;
628 }
629
630 AdjustPitchAlignment(flags, pPitchAlign);
631
632 return valid;
633 }
634
635 /**
636 ***************************************************************************************************
637 * EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled
638 *
639 * @brief
640 * Compute 1D tiled surface alignment, calculation results are returned through
641 * output parameters.
642 *
643 * @return
644 * TRUE if no error occurs
645 ***************************************************************************************************
646 */
647 BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMicroTiled(
648 AddrTileMode tileMode, ///< [in] tile mode
649 UINT_32 bpp, ///< [in] bits per pixel
650 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
651 UINT_32 mipLevel, ///< [in] mip level
652 UINT_32 numSamples, ///< [in] number of samples
653 UINT_32* pBaseAlign, ///< [out] base address alignment in bytes
654 UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels
655 UINT_32* pHeightAlign ///< [out] height alignment in pixels
656 ) const
657 {
658 BOOL_32 valid = TRUE;
659
660 //
661 // The required alignment for base is the pipe interleave size.
662 //
663 *pBaseAlign = m_pipeInterleaveBytes;
664
665 *pPitchAlign = HwlGetPitchAlignmentMicroTiled(tileMode, bpp, flags, numSamples);
666
667 *pHeightAlign = MicroTileHeight;
668
669 AdjustPitchAlignment(flags, pPitchAlign);
670
671 // ECR#393489
672 // Workaround 2 for 1D tiling - There is HW bug for Carrizo
673 // where it requires the following alignments for 1D tiling.
674 if (flags.czDispCompatible && (mipLevel == 0))
675 {
676 *pBaseAlign = PowTwoAlign(*pBaseAlign, 4096); //Base address MOD 4096 = 0
677 *pPitchAlign = PowTwoAlign(*pPitchAlign, 512 / (BITS_TO_BYTES(bpp))); //(8 lines * pitch * bytes per pixel) MOD 4096 = 0
678 }
679 // end Carrizo workaround for 1D tilling
680
681 return valid;
682 }
683
684
685 /**
686 ***************************************************************************************************
687 * EgBasedAddrLib::HwlReduceBankWidthHeight
688 *
689 * @brief
690 * Additional checks, reduce bankHeight/bankWidth if needed and possible
691 * tileSize*BANK_WIDTH*BANK_HEIGHT <= ROW_SIZE
692 *
693 * @return
694 * TRUE if no error occurs
695 ***************************************************************************************************
696 */
697 BOOL_32 EgBasedAddrLib::HwlReduceBankWidthHeight(
698 UINT_32 tileSize, ///< [in] tile size
699 UINT_32 bpp, ///< [in] bits per pixel
700 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
701 UINT_32 numSamples, ///< [in] number of samples
702 UINT_32 bankHeightAlign, ///< [in] bank height alignment
703 UINT_32 pipes, ///< [in] pipes
704 ADDR_TILEINFO* pTileInfo ///< [in/out] bank structure.
705 ) const
706 {
707 UINT_32 macroAspectAlign;
708 BOOL_32 valid = TRUE;
709
710 if (tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize)
711 {
712 BOOL_32 stillGreater = TRUE;
713
714 // Try reducing bankWidth first
715 if (stillGreater && pTileInfo->bankWidth > 1)
716 {
717 while (stillGreater && pTileInfo->bankWidth > 0)
718 {
719 pTileInfo->bankWidth >>= 1;
720
721 if (pTileInfo->bankWidth == 0)
722 {
723 pTileInfo->bankWidth = 1;
724 break;
725 }
726
727 stillGreater =
728 tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize;
729 }
730
731 // bankWidth is reduced above, so we need to recalculate bankHeight and ratio
732 bankHeightAlign = Max(1u,
733 m_pipeInterleaveBytes * m_bankInterleave /
734 (tileSize * pTileInfo->bankWidth)
735 );
736
737 // We cannot increase bankHeight so just assert this case.
738 ADDR_ASSERT((pTileInfo->bankHeight % bankHeightAlign) == 0);
739
740 if (numSamples == 1)
741 {
742 macroAspectAlign = Max(1u,
743 m_pipeInterleaveBytes * m_bankInterleave /
744 (tileSize * pipes * pTileInfo->bankWidth)
745 );
746 pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio,
747 macroAspectAlign);
748 }
749 }
750
751 // Early quit bank_height degradation for "64" bit z buffer
752 if (flags.depth && bpp >= 64)
753 {
754 stillGreater = FALSE;
755 }
756
757 // Then try reducing bankHeight
758 if (stillGreater && pTileInfo->bankHeight > bankHeightAlign)
759 {
760 while (stillGreater && pTileInfo->bankHeight > bankHeightAlign)
761 {
762 pTileInfo->bankHeight >>= 1;
763
764 if (pTileInfo->bankHeight < bankHeightAlign)
765 {
766 pTileInfo->bankHeight = bankHeightAlign;
767 break;
768 }
769
770 stillGreater =
771 tileSize * pTileInfo->bankWidth * pTileInfo->bankHeight > m_rowSize;
772 }
773 }
774
775 valid = !stillGreater;
776
777 // Generate a warning if we still fail to meet this constraint
778 if (!valid)
779 {
780 ADDR_WARN(
781 0, ("TILE_SIZE(%d)*BANK_WIDTH(%d)*BANK_HEIGHT(%d) <= ROW_SIZE(%d)",
782 tileSize, pTileInfo->bankWidth, pTileInfo->bankHeight, m_rowSize));
783 }
784 }
785
786 return valid;
787 }
788
789 /**
790 ***************************************************************************************************
791 * EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled
792 *
793 * @brief
794 * Compute 2D tiled surface alignment, calculation results are returned through
795 * output parameters.
796 *
797 * @return
798 * TRUE if no error occurs
799 ***************************************************************************************************
800 */
801 BOOL_32 EgBasedAddrLib::ComputeSurfaceAlignmentsMacroTiled(
802 AddrTileMode tileMode, ///< [in] tile mode
803 UINT_32 bpp, ///< [in] bits per pixel
804 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
805 UINT_32 mipLevel, ///< [in] mip level
806 UINT_32 numSamples, ///< [in] number of samples
807 ADDR_TILEINFO* pTileInfo, ///< [in/out] bank structure.
808 UINT_32* pBaseAlign, ///< [out] base address alignment in bytes
809 UINT_32* pPitchAlign, ///< [out] pitch alignment in pixels
810 UINT_32* pHeightAlign ///< [out] height alignment in pixels
811 ) const
812 {
813 BOOL_32 valid = SanityCheckMacroTiled(pTileInfo);
814
815 if (valid)
816 {
817 UINT_32 macroTileWidth;
818 UINT_32 macroTileHeight;
819
820 UINT_32 tileSize;
821 UINT_32 bankHeightAlign;
822 UINT_32 macroAspectAlign;
823
824 UINT_32 thickness = ComputeSurfaceThickness(tileMode);
825 UINT_32 pipes = HwlGetPipes(pTileInfo);
826
827 //
828 // Align bank height first according to latest h/w spec
829 //
830
831 // tile_size = MIN(tile_split, 64 * tile_thickness * element_bytes * num_samples)
832 tileSize = Min(pTileInfo->tileSplitBytes,
833 BITS_TO_BYTES(64 * thickness * bpp * numSamples));
834
835 // bank_height_align =
836 // MAX(1, (pipe_interleave_bytes * bank_interleave)/(tile_size*bank_width))
837 bankHeightAlign = Max(1u,
838 m_pipeInterleaveBytes * m_bankInterleave /
839 (tileSize * pTileInfo->bankWidth)
840 );
841
842 pTileInfo->bankHeight = PowTwoAlign(pTileInfo->bankHeight, bankHeightAlign);
843
844 // num_pipes * bank_width * macro_tile_aspect >=
845 // (pipe_interleave_size * bank_interleave) / tile_size
846 if (numSamples == 1)
847 {
848 // this restriction is only for mipmap (mipmap's numSamples must be 1)
849 macroAspectAlign = Max(1u,
850 m_pipeInterleaveBytes * m_bankInterleave /
851 (tileSize * pipes * pTileInfo->bankWidth)
852 );
853 pTileInfo->macroAspectRatio = PowTwoAlign(pTileInfo->macroAspectRatio, macroAspectAlign);
854 }
855
856 valid = HwlReduceBankWidthHeight(tileSize,
857 bpp,
858 flags,
859 numSamples,
860 bankHeightAlign,
861 pipes,
862 pTileInfo);
863
864 //
865 // The required granularity for pitch is the macro tile width.
866 //
867 macroTileWidth = MicroTileWidth * pTileInfo->bankWidth * pipes *
868 pTileInfo->macroAspectRatio;
869
870 *pPitchAlign = macroTileWidth;
871
872 AdjustPitchAlignment(flags, pPitchAlign);
873
874 //
875 // The required granularity for height is the macro tile height.
876 //
877 macroTileHeight = MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks /
878 pTileInfo->macroAspectRatio;
879
880 *pHeightAlign = macroTileHeight;
881
882 //
883 // Compute base alignment
884 //
885 *pBaseAlign = pipes *
886 pTileInfo->bankWidth * pTileInfo->banks * pTileInfo->bankHeight * tileSize;
887
888 if ((mipLevel == 0) && (flags.prt) && (m_chipFamily == ADDR_CHIP_FAMILY_SI))
889 {
890 static const UINT_32 PrtTileSize = 0x10000;
891
892 UINT_32 macroTileSize = macroTileWidth * macroTileHeight * numSamples * bpp / 8;
893
894 if (macroTileSize < PrtTileSize)
895 {
896 UINT_32 numMacroTiles = PrtTileSize / macroTileSize;
897
898 ADDR_ASSERT((PrtTileSize % macroTileSize) == 0);
899
900 *pPitchAlign *= numMacroTiles;
901 *pBaseAlign *= numMacroTiles;
902 }
903 }
904 }
905
906 return valid;
907 }
908
909 /**
910 ***************************************************************************************************
911 * EgBasedAddrLib::SanityCheckMacroTiled
912 *
913 * @brief
914 * Check if macro-tiled parameters are valid
915 * @return
916 * TRUE if valid
917 ***************************************************************************************************
918 */
919 BOOL_32 EgBasedAddrLib::SanityCheckMacroTiled(
920 ADDR_TILEINFO* pTileInfo ///< [in] macro-tiled parameters
921 ) const
922 {
923 BOOL_32 valid = TRUE;
924 UINT_32 numPipes = HwlGetPipes(pTileInfo);
925
926 switch (pTileInfo->banks)
927 {
928 case 2: //fall through
929 case 4: //fall through
930 case 8: //fall through
931 case 16:
932 break;
933 default:
934 valid = FALSE;
935 break;
936
937 }
938
939 if (valid)
940 {
941 switch (pTileInfo->bankWidth)
942 {
943 case 1: //fall through
944 case 2: //fall through
945 case 4: //fall through
946 case 8:
947 break;
948 default:
949 valid = FALSE;
950 break;
951 }
952 }
953
954 if (valid)
955 {
956 switch (pTileInfo->bankHeight)
957 {
958 case 1: //fall through
959 case 2: //fall through
960 case 4: //fall through
961 case 8:
962 break;
963 default:
964 valid = FALSE;
965 break;
966 }
967 }
968
969 if (valid)
970 {
971 switch (pTileInfo->macroAspectRatio)
972 {
973 case 1: //fall through
974 case 2: //fall through
975 case 4: //fall through
976 case 8:
977 break;
978 default:
979 valid = FALSE;
980 break;
981 }
982 }
983
984 if (valid)
985 {
986 if (pTileInfo->banks < pTileInfo->macroAspectRatio)
987 {
988 // This will generate macro tile height <= 1
989 valid = FALSE;
990 }
991 }
992
993 if (valid)
994 {
995 if (pTileInfo->tileSplitBytes > m_rowSize)
996 {
997 valid = FALSE;
998 }
999 }
1000
1001 if (valid)
1002 {
1003 valid = HwlSanityCheckMacroTiled(pTileInfo);
1004 }
1005
1006 ADDR_ASSERT(valid == TRUE);
1007
1008 // Add this assert for guidance
1009 ADDR_ASSERT(numPipes * pTileInfo->banks >= 4);
1010
1011 return valid;
1012 }
1013
1014 /**
1015 ***************************************************************************************************
1016 * EgBasedAddrLib::ComputeSurfaceMipLevelTileMode
1017 *
1018 * @brief
1019 * Compute valid tile mode for surface mipmap sub-levels
1020 *
1021 * @return
1022 * Suitable tile mode
1023 ***************************************************************************************************
1024 */
1025 AddrTileMode EgBasedAddrLib::ComputeSurfaceMipLevelTileMode(
1026 AddrTileMode baseTileMode, ///< [in] base tile mode
1027 UINT_32 bpp, ///< [in] bits per pixels
1028 UINT_32 pitch, ///< [in] current level pitch
1029 UINT_32 height, ///< [in] current level height
1030 UINT_32 numSlices, ///< [in] current number of slices
1031 UINT_32 numSamples, ///< [in] number of samples
1032 UINT_32 pitchAlign, ///< [in] pitch alignment
1033 UINT_32 heightAlign, ///< [in] height alignment
1034 ADDR_TILEINFO* pTileInfo ///< [in] ptr to bank structure
1035 ) const
1036 {
1037 UINT_32 bytesPerTile;
1038
1039 AddrTileMode expTileMode = baseTileMode;
1040 UINT_32 microTileThickness = ComputeSurfaceThickness(expTileMode);
1041 UINT_32 interleaveSize = m_pipeInterleaveBytes * m_bankInterleave;
1042
1043 //
1044 // Compute the size of a slice.
1045 //
1046 bytesPerTile = BITS_TO_BYTES(MicroTilePixels * microTileThickness * NextPow2(bpp) * numSamples);
1047
1048 //
1049 // Reduce tiling mode from thick to thin if the number of slices is less than the
1050 // micro tile thickness.
1051 //
1052 if (numSlices < microTileThickness)
1053 {
1054 expTileMode = HwlDegradeThickTileMode(expTileMode, numSlices, &bytesPerTile);
1055 }
1056
1057 if (bytesPerTile > pTileInfo->tileSplitBytes)
1058 {
1059 bytesPerTile = pTileInfo->tileSplitBytes;
1060 }
1061
1062 UINT_32 threshold1 =
1063 bytesPerTile * HwlGetPipes(pTileInfo) * pTileInfo->bankWidth * pTileInfo->macroAspectRatio;
1064
1065 UINT_32 threshold2 =
1066 bytesPerTile * pTileInfo->bankWidth * pTileInfo->bankHeight;
1067
1068 //
1069 // Reduce the tile mode from 2D/3D to 1D in following conditions
1070 //
1071 switch (expTileMode)
1072 {
1073 case ADDR_TM_2D_TILED_THIN1: //fall through
1074 case ADDR_TM_3D_TILED_THIN1:
1075 case ADDR_TM_PRT_TILED_THIN1:
1076 case ADDR_TM_PRT_2D_TILED_THIN1:
1077 case ADDR_TM_PRT_3D_TILED_THIN1:
1078 if ((pitch < pitchAlign) ||
1079 (height < heightAlign) ||
1080 (interleaveSize > threshold1) ||
1081 (interleaveSize > threshold2))
1082 {
1083 expTileMode = ADDR_TM_1D_TILED_THIN1;
1084 }
1085 break;
1086 case ADDR_TM_2D_TILED_THICK: //fall through
1087 case ADDR_TM_3D_TILED_THICK:
1088 case ADDR_TM_2D_TILED_XTHICK:
1089 case ADDR_TM_3D_TILED_XTHICK:
1090 case ADDR_TM_PRT_TILED_THICK:
1091 case ADDR_TM_PRT_2D_TILED_THICK:
1092 case ADDR_TM_PRT_3D_TILED_THICK:
1093 if ((pitch < pitchAlign) ||
1094 (height < heightAlign))
1095 {
1096 expTileMode = ADDR_TM_1D_TILED_THICK;
1097 }
1098 break;
1099 default:
1100 break;
1101 }
1102
1103 return expTileMode;
1104 }
1105
1106 /**
1107 ***************************************************************************************************
1108 * EgBasedAddrLib::HwlDegradeBaseLevel
1109 * @brief
1110 * Check if degrade is needed for base level
1111 * @return
1112 * TRUE if degrade is suggested
1113 ***************************************************************************************************
1114 */
1115 BOOL_32 EgBasedAddrLib::HwlDegradeBaseLevel(
1116 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn) const
1117 {
1118 BOOL_32 degrade = FALSE;
1119 BOOL_32 valid = TRUE;
1120
1121 ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
1122
1123 UINT_32 baseAlign;
1124 UINT_32 pitchAlign;
1125 UINT_32 heightAlign;
1126
1127 ADDR_ASSERT(pIn->pTileInfo);
1128 ADDR_TILEINFO tileInfo = *pIn->pTileInfo;
1129 ADDR_COMPUTE_SURFACE_INFO_OUTPUT out = {0};
1130
1131 if (UseTileIndex(pIn->tileIndex))
1132 {
1133 out.tileIndex = pIn->tileIndex;
1134 out.macroModeIndex = TileIndexInvalid;
1135 }
1136
1137 HwlSetupTileInfo(pIn->tileMode,
1138 pIn->flags,
1139 pIn->bpp,
1140 pIn->width,
1141 pIn->height,
1142 pIn->numSamples,
1143 &tileInfo,
1144 &tileInfo,
1145 pIn->tileType,
1146 &out);
1147
1148 valid = ComputeSurfaceAlignmentsMacroTiled(pIn->tileMode,
1149 pIn->bpp,
1150 pIn->flags,
1151 pIn->mipLevel,
1152 pIn->numSamples,
1153 &tileInfo,
1154 &baseAlign,
1155 &pitchAlign,
1156 &heightAlign);
1157
1158 if (valid)
1159 {
1160 degrade = (pIn->width < pitchAlign || pIn->height < heightAlign);
1161 }
1162 else
1163 {
1164 degrade = TRUE;
1165 }
1166
1167 return degrade;
1168 }
1169
1170 /**
1171 ***************************************************************************************************
1172 * EgBasedAddrLib::HwlDegradeThickTileMode
1173 *
1174 * @brief
1175 * Degrades valid tile mode for thick modes if needed
1176 *
1177 * @return
1178 * Suitable tile mode
1179 ***************************************************************************************************
1180 */
1181 AddrTileMode EgBasedAddrLib::HwlDegradeThickTileMode(
1182 AddrTileMode baseTileMode, ///< [in] base tile mode
1183 UINT_32 numSlices, ///< [in] current number of slices
1184 UINT_32* pBytesPerTile ///< [in/out] pointer to bytes per slice
1185 ) const
1186 {
1187 ADDR_ASSERT(numSlices < ComputeSurfaceThickness(baseTileMode));
1188 // if pBytesPerTile is NULL, this is a don't-care....
1189 UINT_32 bytesPerTile = pBytesPerTile != NULL ? *pBytesPerTile : 64;
1190
1191 AddrTileMode expTileMode = baseTileMode;
1192 switch (baseTileMode)
1193 {
1194 case ADDR_TM_1D_TILED_THICK:
1195 expTileMode = ADDR_TM_1D_TILED_THIN1;
1196 bytesPerTile >>= 2;
1197 break;
1198 case ADDR_TM_2D_TILED_THICK:
1199 expTileMode = ADDR_TM_2D_TILED_THIN1;
1200 bytesPerTile >>= 2;
1201 break;
1202 case ADDR_TM_3D_TILED_THICK:
1203 expTileMode = ADDR_TM_3D_TILED_THIN1;
1204 bytesPerTile >>= 2;
1205 break;
1206 case ADDR_TM_2D_TILED_XTHICK:
1207 if (numSlices < ThickTileThickness)
1208 {
1209 expTileMode = ADDR_TM_2D_TILED_THIN1;
1210 bytesPerTile >>= 3;
1211 }
1212 else
1213 {
1214 expTileMode = ADDR_TM_2D_TILED_THICK;
1215 bytesPerTile >>= 1;
1216 }
1217 break;
1218 case ADDR_TM_3D_TILED_XTHICK:
1219 if (numSlices < ThickTileThickness)
1220 {
1221 expTileMode = ADDR_TM_3D_TILED_THIN1;
1222 bytesPerTile >>= 3;
1223 }
1224 else
1225 {
1226 expTileMode = ADDR_TM_3D_TILED_THICK;
1227 bytesPerTile >>= 1;
1228 }
1229 break;
1230 default:
1231 ADDR_ASSERT_ALWAYS();
1232 break;
1233 }
1234
1235 if (pBytesPerTile != NULL)
1236 {
1237 *pBytesPerTile = bytesPerTile;
1238 }
1239
1240 return expTileMode;
1241 }
1242
1243 /**
1244 ***************************************************************************************************
1245 * EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord
1246 *
1247 * @brief
1248 * Compute surface address from given coord (x, y, slice,sample)
1249 *
1250 * @return
1251 * Address in bytes
1252 ***************************************************************************************************
1253 */
1254 UINT_64 EgBasedAddrLib::DispatchComputeSurfaceAddrFromCoord(
1255 const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
1256 ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
1257 ) const
1258 {
1259 UINT_32 x = pIn->x;
1260 UINT_32 y = pIn->y;
1261 UINT_32 slice = pIn->slice;
1262 UINT_32 sample = pIn->sample;
1263 UINT_32 bpp = pIn->bpp;
1264 UINT_32 pitch = pIn->pitch;
1265 UINT_32 height = pIn->height;
1266 UINT_32 numSlices = pIn->numSlices;
1267 UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples);
1268 UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
1269 AddrTileMode tileMode = pIn->tileMode;
1270 AddrTileType microTileType = pIn->tileType;
1271 BOOL_32 ignoreSE = pIn->ignoreSE;
1272 BOOL_32 isDepthSampleOrder = pIn->isDepth;
1273 ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
1274
1275 UINT_32* pBitPosition = &pOut->bitPosition;
1276 UINT_64 addr;
1277
1278 #if ADDR_AM_BUILD
1279 UINT_32 addr5Bit = 0;
1280 UINT_32 addr5Swizzle = pIn->addr5Swizzle;
1281 BOOL_32 is32ByteTile = pIn->is32ByteTile;
1282 #endif
1283
1284 // ADDR_DEPTH_SAMPLE_ORDER = non-disp + depth-sample-order
1285 if (microTileType == ADDR_DEPTH_SAMPLE_ORDER)
1286 {
1287 isDepthSampleOrder = TRUE;
1288 }
1289
1290 if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
1291 {
1292 if (numFrags != numSamples)
1293 {
1294 numSamples = numFrags;
1295 ADDR_ASSERT(sample < numSamples);
1296 }
1297
1298 /// @note
1299 /// 128 bit/thick tiled surface doesn't support display tiling and
1300 /// mipmap chain must have the same tileType, so please fill tileType correctly
1301 if (!IsLinear(pIn->tileMode))
1302 {
1303 if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1)
1304 {
1305 ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE);
1306 }
1307 }
1308 }
1309
1310 switch (tileMode)
1311 {
1312 case ADDR_TM_LINEAR_GENERAL://fall through
1313 case ADDR_TM_LINEAR_ALIGNED:
1314 addr = ComputeSurfaceAddrFromCoordLinear(x,
1315 y,
1316 slice,
1317 sample,
1318 bpp,
1319 pitch,
1320 height,
1321 numSlices,
1322 pBitPosition);
1323 break;
1324 case ADDR_TM_1D_TILED_THIN1://fall through
1325 case ADDR_TM_1D_TILED_THICK:
1326 addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
1327 y,
1328 slice,
1329 sample,
1330 bpp,
1331 pitch,
1332 height,
1333 numSamples,
1334 tileMode,
1335 microTileType,
1336 isDepthSampleOrder,
1337 pBitPosition);
1338 break;
1339 case ADDR_TM_2D_TILED_THIN1: //fall through
1340 case ADDR_TM_2D_TILED_THICK: //fall through
1341 case ADDR_TM_3D_TILED_THIN1: //fall through
1342 case ADDR_TM_3D_TILED_THICK: //fall through
1343 case ADDR_TM_2D_TILED_XTHICK: //fall through
1344 case ADDR_TM_3D_TILED_XTHICK: //fall through
1345 case ADDR_TM_PRT_TILED_THIN1: //fall through
1346 case ADDR_TM_PRT_2D_TILED_THIN1://fall through
1347 case ADDR_TM_PRT_3D_TILED_THIN1://fall through
1348 case ADDR_TM_PRT_TILED_THICK: //fall through
1349 case ADDR_TM_PRT_2D_TILED_THICK://fall through
1350 case ADDR_TM_PRT_3D_TILED_THICK:
1351 UINT_32 pipeSwizzle;
1352 UINT_32 bankSwizzle;
1353
1354 if (m_configFlags.useCombinedSwizzle)
1355 {
1356 ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
1357 &bankSwizzle, &pipeSwizzle);
1358 }
1359 else
1360 {
1361 pipeSwizzle = pIn->pipeSwizzle;
1362 bankSwizzle = pIn->bankSwizzle;
1363 }
1364
1365 addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
1366 y,
1367 slice,
1368 sample,
1369 bpp,
1370 pitch,
1371 height,
1372 numSamples,
1373 tileMode,
1374 microTileType,
1375 ignoreSE,
1376 isDepthSampleOrder,
1377 pipeSwizzle,
1378 bankSwizzle,
1379 pTileInfo,
1380 pBitPosition);
1381 break;
1382 default:
1383 addr = 0;
1384 ADDR_ASSERT_ALWAYS();
1385 break;
1386 }
1387
1388 #if ADDR_AM_BUILD
1389 if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
1390 {
1391 if (addr5Swizzle && isDepthSampleOrder && is32ByteTile)
1392 {
1393 UINT_32 tx = x >> 3;
1394 UINT_32 ty = y >> 3;
1395 UINT_32 tileBits = ((ty&0x3) << 2) | (tx&0x3);
1396
1397 tileBits = tileBits & addr5Swizzle;
1398 addr5Bit = XorReduce(tileBits, 4);
1399
1400 addr = addr | static_cast<UINT_64>(addr5Bit << 5);
1401 }
1402 }
1403 #endif
1404
1405 return addr;
1406 }
1407
1408 /**
1409 ***************************************************************************************************
1410 * EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled
1411 *
1412 * @brief
1413 * Computes the surface address and bit position from a
1414 * coordinate for 2D tilied (macro tiled)
1415 * @return
1416 * The byte address
1417 ***************************************************************************************************
1418 */
1419 UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMacroTiled(
1420 UINT_32 x, ///< [in] x coordinate
1421 UINT_32 y, ///< [in] y coordinate
1422 UINT_32 slice, ///< [in] slice index
1423 UINT_32 sample, ///< [in] sample index
1424 UINT_32 bpp, ///< [in] bits per pixel
1425 UINT_32 pitch, ///< [in] surface pitch, in pixels
1426 UINT_32 height, ///< [in] surface height, in pixels
1427 UINT_32 numSamples, ///< [in] number of samples
1428 AddrTileMode tileMode, ///< [in] tile mode
1429 AddrTileType microTileType, ///< [in] micro tiling type
1430 BOOL_32 ignoreSE, ///< [in] TRUE if shader enginers can be ignored
1431 BOOL_32 isDepthSampleOrder, ///< [in] TRUE if it depth sample ordering is used
1432 UINT_32 pipeSwizzle, ///< [in] pipe swizzle
1433 UINT_32 bankSwizzle, ///< [in] bank swizzle
1434 ADDR_TILEINFO* pTileInfo, ///< [in] bank structure
1435 /// **All fields to be valid on entry**
1436 UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this
1437 ) const
1438 {
1439 UINT_64 addr;
1440
1441 UINT_32 microTileBytes;
1442 UINT_32 microTileBits;
1443 UINT_32 sampleOffset;
1444 UINT_32 pixelIndex;
1445 UINT_32 pixelOffset;
1446 UINT_32 elementOffset;
1447 UINT_32 tileSplitSlice;
1448 UINT_32 pipe;
1449 UINT_32 bank;
1450 UINT_64 sliceBytes;
1451 UINT_64 sliceOffset;
1452 UINT_32 macroTilePitch;
1453 UINT_32 macroTileHeight;
1454 UINT_32 macroTilesPerRow;
1455 UINT_32 macroTilesPerSlice;
1456 UINT_64 macroTileBytes;
1457 UINT_32 macroTileIndexX;
1458 UINT_32 macroTileIndexY;
1459 UINT_64 macroTileOffset;
1460 UINT_64 totalOffset;
1461 UINT_64 pipeInterleaveMask;
1462 UINT_64 bankInterleaveMask;
1463 UINT_64 pipeInterleaveOffset;
1464 UINT_32 bankInterleaveOffset;
1465 UINT_64 offset;
1466 UINT_32 tileRowIndex;
1467 UINT_32 tileColumnIndex;
1468 UINT_32 tileIndex;
1469 UINT_32 tileOffset;
1470
1471 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
1472
1473 //
1474 // Compute the number of group, pipe, and bank bits.
1475 //
1476 UINT_32 numPipes = HwlGetPipes(pTileInfo);
1477 UINT_32 numPipeInterleaveBits = Log2(m_pipeInterleaveBytes);
1478 UINT_32 numPipeBits = Log2(numPipes);
1479 UINT_32 numBankInterleaveBits = Log2(m_bankInterleave);
1480 UINT_32 numBankBits = Log2(pTileInfo->banks);
1481
1482 //
1483 // Compute the micro tile size.
1484 //
1485 microTileBits = MicroTilePixels * microTileThickness * bpp * numSamples;
1486
1487 microTileBytes = microTileBits / 8;
1488 //
1489 // Compute the pixel index within the micro tile.
1490 //
1491 pixelIndex = ComputePixelIndexWithinMicroTile(x,
1492 y,
1493 slice,
1494 bpp,
1495 tileMode,
1496 microTileType);
1497
1498 //
1499 // Compute the sample offset and pixel offset.
1500 //
1501 if (isDepthSampleOrder)
1502 {
1503 //
1504 // For depth surfaces, samples are stored contiguously for each element, so the sample
1505 // offset is the sample number times the element size.
1506 //
1507 sampleOffset = sample * bpp;
1508 pixelOffset = pixelIndex * bpp * numSamples;
1509 }
1510 else
1511 {
1512 //
1513 // For color surfaces, all elements for a particular sample are stored contiguously, so
1514 // the sample offset is the sample number times the micro tile size divided yBit the number
1515 // of samples.
1516 //
1517 sampleOffset = sample * (microTileBits / numSamples);
1518 pixelOffset = pixelIndex * bpp;
1519 }
1520
1521 //
1522 // Compute the element offset.
1523 //
1524 elementOffset = pixelOffset + sampleOffset;
1525
1526 *pBitPosition = static_cast<UINT_32>(elementOffset % 8);
1527
1528 elementOffset /= 8; //bit-to-byte
1529
1530 //
1531 // Determine if tiles need to be split across slices.
1532 //
1533 // If the size of the micro tile is larger than the tile split size, then the tile will be
1534 // split across multiple slices.
1535 //
1536 UINT_32 slicesPerTile = 1;
1537
1538 if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1))
1539 { //don't support for thick mode
1540
1541 //
1542 // Compute the number of slices per tile.
1543 //
1544 slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes;
1545
1546 //
1547 // Compute the tile split slice number for use in rotating the bank.
1548 //
1549 tileSplitSlice = elementOffset / pTileInfo->tileSplitBytes;
1550
1551 //
1552 // Adjust the element offset to account for the portion of the tile that is being moved to
1553 // a new slice..
1554 //
1555 elementOffset %= pTileInfo->tileSplitBytes;
1556
1557 //
1558 // Adjust the microTileBytes size to tileSplitBytes size since
1559 // a new slice..
1560 //
1561 microTileBytes = pTileInfo->tileSplitBytes;
1562 }
1563 else
1564 {
1565 tileSplitSlice = 0;
1566 }
1567
1568 //
1569 // Compute macro tile pitch and height.
1570 //
1571 macroTilePitch =
1572 (MicroTileWidth * pTileInfo->bankWidth * numPipes) * pTileInfo->macroAspectRatio;
1573 macroTileHeight =
1574 (MicroTileHeight * pTileInfo->bankHeight * pTileInfo->banks) / pTileInfo->macroAspectRatio;
1575
1576 //
1577 // Compute the number of bytes per macro tile. Note: bytes of the same bank/pipe actually
1578 //
1579 macroTileBytes =
1580 static_cast<UINT_64>(microTileBytes) *
1581 (macroTilePitch / MicroTileWidth) * (macroTileHeight / MicroTileHeight) /
1582 (numPipes * pTileInfo->banks);
1583
1584 //
1585 // Compute the number of macro tiles per row.
1586 //
1587 macroTilesPerRow = pitch / macroTilePitch;
1588
1589 //
1590 // Compute the offset to the macro tile containing the specified coordinate.
1591 //
1592 macroTileIndexX = x / macroTilePitch;
1593 macroTileIndexY = y / macroTileHeight;
1594 macroTileOffset = ((macroTileIndexY * macroTilesPerRow) + macroTileIndexX) * macroTileBytes;
1595
1596 //
1597 // Compute the number of macro tiles per slice.
1598 //
1599 macroTilesPerSlice = macroTilesPerRow * (height / macroTileHeight);
1600
1601 //
1602 // Compute the slice size.
1603 //
1604 sliceBytes = macroTilesPerSlice * macroTileBytes;
1605
1606 //
1607 // Compute the slice offset.
1608 //
1609 sliceOffset = sliceBytes * (tileSplitSlice + slicesPerTile * (slice / microTileThickness));
1610
1611 //
1612 // Compute tile offest
1613 //
1614 tileRowIndex = (y / MicroTileHeight) % pTileInfo->bankHeight;
1615 tileColumnIndex = ((x / MicroTileWidth) / numPipes) % pTileInfo->bankWidth;
1616 tileIndex = (tileRowIndex * pTileInfo->bankWidth) + tileColumnIndex;
1617 tileOffset = tileIndex * microTileBytes;
1618
1619 //
1620 // Combine the slice offset and macro tile offset with the pixel and sample offsets, accounting
1621 // for the pipe and bank bits in the middle of the address.
1622 //
1623 totalOffset = sliceOffset + macroTileOffset + elementOffset + tileOffset;
1624
1625 //
1626 // Get the pipe and bank.
1627 //
1628
1629 // when the tileMode is PRT type, then adjust x and y coordinates
1630 if (IsPrtNoRotationTileMode(tileMode))
1631 {
1632 x = x % macroTilePitch;
1633 y = y % macroTileHeight;
1634 }
1635
1636 pipe = ComputePipeFromCoord(x,
1637 y,
1638 slice,
1639 tileMode,
1640 pipeSwizzle,
1641 ignoreSE,
1642 pTileInfo);
1643
1644 bank = ComputeBankFromCoord(x,
1645 y,
1646 slice,
1647 tileMode,
1648 bankSwizzle,
1649 tileSplitSlice,
1650 pTileInfo);
1651
1652
1653 //
1654 // Split the offset to put some bits below the pipe+bank bits and some above.
1655 //
1656 pipeInterleaveMask = (1 << numPipeInterleaveBits) - 1;
1657 bankInterleaveMask = (1 << numBankInterleaveBits) - 1;
1658 pipeInterleaveOffset = totalOffset & pipeInterleaveMask;
1659 bankInterleaveOffset = static_cast<UINT_32>((totalOffset >> numPipeInterleaveBits) &
1660 bankInterleaveMask);
1661 offset = totalOffset >> (numPipeInterleaveBits + numBankInterleaveBits);
1662
1663 //
1664 // Assemble the address from its components.
1665 //
1666 addr = pipeInterleaveOffset;
1667 // This is to remove /analyze warnings
1668 UINT_32 pipeBits = pipe << numPipeInterleaveBits;
1669 UINT_32 bankInterleaveBits = bankInterleaveOffset << (numPipeInterleaveBits + numPipeBits);
1670 UINT_32 bankBits = bank << (numPipeInterleaveBits + numPipeBits +
1671 numBankInterleaveBits);
1672 UINT_64 offsetBits = offset << (numPipeInterleaveBits + numPipeBits +
1673 numBankInterleaveBits + numBankBits);
1674
1675 addr |= pipeBits;
1676 addr |= bankInterleaveBits;
1677 addr |= bankBits;
1678 addr |= offsetBits;
1679
1680 return addr;
1681 }
1682
1683 /**
1684 ***************************************************************************************************
1685 * EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled
1686 *
1687 * @brief
1688 * Computes the surface address and bit position from a coordinate for 1D tilied
1689 * (micro tiled)
1690 * @return
1691 * The byte address
1692 ***************************************************************************************************
1693 */
1694 UINT_64 EgBasedAddrLib::ComputeSurfaceAddrFromCoordMicroTiled(
1695 UINT_32 x, ///< [in] x coordinate
1696 UINT_32 y, ///< [in] y coordinate
1697 UINT_32 slice, ///< [in] slice index
1698 UINT_32 sample, ///< [in] sample index
1699 UINT_32 bpp, ///< [in] bits per pixel
1700 UINT_32 pitch, ///< [in] pitch, in pixels
1701 UINT_32 height, ///< [in] height, in pixels
1702 UINT_32 numSamples, ///< [in] number of samples
1703 AddrTileMode tileMode, ///< [in] tile mode
1704 AddrTileType microTileType, ///< [in] micro tiling type
1705 BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample ordering is used
1706 UINT_32* pBitPosition ///< [out] bit position, e.g. FMT_1 will use this
1707 ) const
1708 {
1709 UINT_64 addr = 0;
1710
1711 UINT_32 microTileBytes;
1712 UINT_64 sliceBytes;
1713 UINT_32 microTilesPerRow;
1714 UINT_32 microTileIndexX;
1715 UINT_32 microTileIndexY;
1716 UINT_32 microTileIndexZ;
1717 UINT_64 sliceOffset;
1718 UINT_64 microTileOffset;
1719 UINT_32 sampleOffset;
1720 UINT_32 pixelIndex;
1721 UINT_32 pixelOffset;
1722
1723 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
1724
1725 //
1726 // Compute the micro tile size.
1727 //
1728 microTileBytes = BITS_TO_BYTES(MicroTilePixels * microTileThickness * bpp * numSamples);
1729
1730 //
1731 // Compute the slice size.
1732 //
1733 sliceBytes =
1734 BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * microTileThickness * bpp * numSamples);
1735
1736 //
1737 // Compute the number of micro tiles per row.
1738 //
1739 microTilesPerRow = pitch / MicroTileWidth;
1740
1741 //
1742 // Compute the micro tile index.
1743 //
1744 microTileIndexX = x / MicroTileWidth;
1745 microTileIndexY = y / MicroTileHeight;
1746 microTileIndexZ = slice / microTileThickness;
1747
1748 //
1749 // Compute the slice offset.
1750 //
1751 sliceOffset = static_cast<UINT_64>(microTileIndexZ) * sliceBytes;
1752
1753 //
1754 // Compute the offset to the micro tile containing the specified coordinate.
1755 //
1756 microTileOffset = (static_cast<UINT_64>(microTileIndexY) * microTilesPerRow + microTileIndexX) *
1757 microTileBytes;
1758
1759 //
1760 // Compute the pixel index within the micro tile.
1761 //
1762 pixelIndex = ComputePixelIndexWithinMicroTile(x,
1763 y,
1764 slice,
1765 bpp,
1766 tileMode,
1767 microTileType);
1768
1769 // Compute the sample offset.
1770 //
1771 if (isDepthSampleOrder)
1772 {
1773 //
1774 // For depth surfaces, samples are stored contiguously for each element, so the sample
1775 // offset is the sample number times the element size.
1776 //
1777 sampleOffset = sample * bpp;
1778 pixelOffset = pixelIndex * bpp * numSamples;
1779 }
1780 else
1781 {
1782 //
1783 // For color surfaces, all elements for a particular sample are stored contiguously, so
1784 // the sample offset is the sample number times the micro tile size divided yBit the number
1785 // of samples.
1786 //
1787 sampleOffset = sample * (microTileBytes*8 / numSamples);
1788 pixelOffset = pixelIndex * bpp;
1789 }
1790
1791 //
1792 // Compute the bit position of the pixel. Each element is stored with one bit per sample.
1793 //
1794
1795 UINT_32 elemOffset = sampleOffset + pixelOffset;
1796
1797 *pBitPosition = elemOffset % 8;
1798 elemOffset /= 8;
1799
1800 //
1801 // Combine the slice offset, micro tile offset, sample offset, and pixel offsets.
1802 //
1803 addr = sliceOffset + microTileOffset + elemOffset;
1804
1805 return addr;
1806 }
1807
1808 /**
1809 ***************************************************************************************************
1810 * EgBasedAddrLib::HwlComputePixelCoordFromOffset
1811 *
1812 * @brief
1813 * Compute pixel coordinate from offset inside a micro tile
1814 * @return
1815 * N/A
1816 ***************************************************************************************************
1817 */
1818 VOID EgBasedAddrLib::HwlComputePixelCoordFromOffset(
1819 UINT_32 offset, ///< [in] offset inside micro tile in bits
1820 UINT_32 bpp, ///< [in] bits per pixel
1821 UINT_32 numSamples, ///< [in] number of samples
1822 AddrTileMode tileMode, ///< [in] tile mode
1823 UINT_32 tileBase, ///< [in] base offset within a tile
1824 UINT_32 compBits, ///< [in] component bits actually needed(for planar surface)
1825 UINT_32* pX, ///< [out] x coordinate
1826 UINT_32* pY, ///< [out] y coordinate
1827 UINT_32* pSlice, ///< [out] slice index
1828 UINT_32* pSample, ///< [out] sample index
1829 AddrTileType microTileType, ///< [in] micro tiling type
1830 BOOL_32 isDepthSampleOrder ///< [in] TRUE if depth sample order in microtile is used
1831 ) const
1832 {
1833 UINT_32 x = 0;
1834 UINT_32 y = 0;
1835 UINT_32 z = 0;
1836 UINT_32 thickness = ComputeSurfaceThickness(tileMode);
1837
1838 // For planar surface, we adjust offset acoording to tile base
1839 if ((bpp != compBits) && (compBits != 0) && isDepthSampleOrder)
1840 {
1841 offset -= tileBase;
1842
1843 ADDR_ASSERT(microTileType == ADDR_NON_DISPLAYABLE ||
1844 microTileType == ADDR_DEPTH_SAMPLE_ORDER);
1845
1846 bpp = compBits;
1847 }
1848
1849 UINT_32 sampleTileBits;
1850 UINT_32 samplePixelBits;
1851 UINT_32 pixelIndex;
1852
1853 if (isDepthSampleOrder)
1854 {
1855 samplePixelBits = bpp * numSamples;
1856 pixelIndex = offset / samplePixelBits;
1857 *pSample = (offset % samplePixelBits) / bpp;
1858 }
1859 else
1860 {
1861 sampleTileBits = MicroTilePixels * bpp * thickness;
1862 *pSample = offset / sampleTileBits;
1863 pixelIndex = (offset % sampleTileBits) / bpp;
1864 }
1865
1866 if (microTileType != ADDR_THICK)
1867 {
1868 if (microTileType == ADDR_DISPLAYABLE) // displayable
1869 {
1870 switch (bpp)
1871 {
1872 case 8:
1873 x = pixelIndex & 0x7;
1874 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4));
1875 break;
1876 case 16:
1877 x = pixelIndex & 0x7;
1878 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3));
1879 break;
1880 case 32:
1881 x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0));
1882 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2));
1883 break;
1884 case 64:
1885 x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
1886 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
1887 break;
1888 case 128:
1889 x = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,2),_BIT(pixelIndex,1));
1890 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,0));
1891 break;
1892 default:
1893 break;
1894 }
1895 }
1896 else if (microTileType == ADDR_NON_DISPLAYABLE || microTileType == ADDR_DEPTH_SAMPLE_ORDER)
1897 {
1898 x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
1899 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
1900 }
1901 else if (microTileType == ADDR_ROTATED)
1902 {
1903 /*
1904 8-Bit Elements
1905 element_index[5:0] = { x[2], x[0], x[1], y[2], y[1], y[0] }
1906
1907 16-Bit Elements
1908 element_index[5:0] = { x[2], x[1], x[0], y[2], y[1], y[0] }
1909
1910 32-Bit Elements
1911 element_index[5:0] = { x[2], x[1], y[2], x[0], y[1], y[0] }
1912
1913 64-Bit Elements
1914 element_index[5:0] = { y[2], x[2], x[1], y[1], x[0], y[0] }
1915 */
1916 switch(bpp)
1917 {
1918 case 8:
1919 x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,3),_BIT(pixelIndex,4));
1920 y = pixelIndex & 0x7;
1921 break;
1922 case 16:
1923 x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,3));
1924 y = pixelIndex & 0x7;
1925 break;
1926 case 32:
1927 x = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,4),_BIT(pixelIndex,2));
1928 y = Bits2Number(3, _BIT(pixelIndex,3),_BIT(pixelIndex,1),_BIT(pixelIndex,0));
1929 break;
1930 case 64:
1931 x = Bits2Number(3, _BIT(pixelIndex,4),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
1932 y = Bits2Number(3, _BIT(pixelIndex,5),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
1933 break;
1934 default:
1935 ADDR_ASSERT_ALWAYS();
1936 break;
1937 }
1938 }
1939
1940 if (thickness > 1) // thick
1941 {
1942 z = Bits2Number(3, _BIT(pixelIndex,8),_BIT(pixelIndex,7),_BIT(pixelIndex,6));
1943 }
1944 }
1945 else
1946 {
1947 ADDR_ASSERT((m_chipFamily >= ADDR_CHIP_FAMILY_CI) && (thickness > 1));
1948 /*
1949 8-Bit Elements and 16-Bit Elements
1950 element_index[7:0] = { y[2], x[2], z[1], z[0], y[1], x[1], y[0], x[0] }
1951
1952 32-Bit Elements
1953 element_index[7:0] = { y[2], x[2], z[1], y[1], z[0], x[1], y[0], x[0] }
1954
1955 64-Bit Elements and 128-Bit Elements
1956 element_index[7:0] = { y[2], x[2], z[1], y[1], x[1], z[0], y[0], x[0] }
1957
1958 The equation to compute the element index for the extra thick tile:
1959 element_index[8] = z[2]
1960 */
1961 switch (bpp)
1962 {
1963 case 8:
1964 case 16: // fall-through
1965 x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
1966 y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,3),_BIT(pixelIndex,1));
1967 z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,4));
1968 break;
1969 case 32:
1970 x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,2),_BIT(pixelIndex,0));
1971 y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
1972 z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,3));
1973 break;
1974 case 64:
1975 case 128: // fall-through
1976 x = Bits2Number(3, _BIT(pixelIndex,6),_BIT(pixelIndex,3),_BIT(pixelIndex,0));
1977 y = Bits2Number(3, _BIT(pixelIndex,7),_BIT(pixelIndex,4),_BIT(pixelIndex,1));
1978 z = Bits2Number(2, _BIT(pixelIndex,5),_BIT(pixelIndex,2));
1979 break;
1980 default:
1981 ADDR_ASSERT_ALWAYS();
1982 break;
1983 }
1984
1985 if (thickness == 8)
1986 {
1987 z += Bits2Number(3,_BIT(pixelIndex,8),0,0);
1988 }
1989 }
1990
1991 *pX = x;
1992 *pY = y;
1993 *pSlice += z;
1994 }
1995
1996
1997 /**
1998 ***************************************************************************************************
1999 * EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddrDispatch
2000 *
2001 * @brief
2002 * Compute (x,y,slice,sample) coordinates from surface address
2003 * @return
2004 * N/A
2005 ***************************************************************************************************
2006 */
2007 VOID EgBasedAddrLib::DispatchComputeSurfaceCoordFromAddr(
2008 const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
2009 ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
2010 ) const
2011 {
2012 UINT_64 addr = pIn->addr;
2013 UINT_32 bitPosition = pIn->bitPosition;
2014 UINT_32 bpp = pIn->bpp;
2015 UINT_32 pitch = pIn->pitch;
2016 UINT_32 height = pIn->height;
2017 UINT_32 numSlices = pIn->numSlices;
2018 UINT_32 numSamples = ((pIn->numSamples == 0) ? 1 : pIn->numSamples);
2019 UINT_32 numFrags = ((pIn->numFrags == 0) ? numSamples : pIn->numFrags);
2020 AddrTileMode tileMode = pIn->tileMode;
2021 UINT_32 tileBase = pIn->tileBase;
2022 UINT_32 compBits = pIn->compBits;
2023 AddrTileType microTileType = pIn->tileType;
2024 BOOL_32 ignoreSE = pIn->ignoreSE;
2025 BOOL_32 isDepthSampleOrder = pIn->isDepth;
2026 ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
2027
2028 UINT_32* pX = &pOut->x;
2029 UINT_32* pY = &pOut->y;
2030 UINT_32* pSlice = &pOut->slice;
2031 UINT_32* pSample = &pOut->sample;
2032
2033 if (microTileType == ADDR_DEPTH_SAMPLE_ORDER)
2034 {
2035 isDepthSampleOrder = TRUE;
2036 }
2037
2038 if (m_chipFamily >= ADDR_CHIP_FAMILY_NI)
2039 {
2040 if (numFrags != numSamples)
2041 {
2042 numSamples = numFrags;
2043 }
2044
2045 /// @note
2046 /// 128 bit/thick tiled surface doesn't support display tiling and
2047 /// mipmap chain must have the same tileType, so please fill tileType correctly
2048 if (!IsLinear(pIn->tileMode))
2049 {
2050 if (bpp >= 128 || ComputeSurfaceThickness(tileMode) > 1)
2051 {
2052 ADDR_ASSERT(microTileType != ADDR_DISPLAYABLE);
2053 }
2054 }
2055 }
2056
2057 switch (tileMode)
2058 {
2059 case ADDR_TM_LINEAR_GENERAL://fall through
2060 case ADDR_TM_LINEAR_ALIGNED:
2061 ComputeSurfaceCoordFromAddrLinear(addr,
2062 bitPosition,
2063 bpp,
2064 pitch,
2065 height,
2066 numSlices,
2067 pX,
2068 pY,
2069 pSlice,
2070 pSample);
2071 break;
2072 case ADDR_TM_1D_TILED_THIN1://fall through
2073 case ADDR_TM_1D_TILED_THICK:
2074 ComputeSurfaceCoordFromAddrMicroTiled(addr,
2075 bitPosition,
2076 bpp,
2077 pitch,
2078 height,
2079 numSamples,
2080 tileMode,
2081 tileBase,
2082 compBits,
2083 pX,
2084 pY,
2085 pSlice,
2086 pSample,
2087 microTileType,
2088 isDepthSampleOrder);
2089 break;
2090 case ADDR_TM_2D_TILED_THIN1: //fall through
2091 case ADDR_TM_2D_TILED_THICK: //fall through
2092 case ADDR_TM_3D_TILED_THIN1: //fall through
2093 case ADDR_TM_3D_TILED_THICK: //fall through
2094 case ADDR_TM_2D_TILED_XTHICK: //fall through
2095 case ADDR_TM_3D_TILED_XTHICK: //fall through
2096 case ADDR_TM_PRT_TILED_THIN1: //fall through
2097 case ADDR_TM_PRT_2D_TILED_THIN1://fall through
2098 case ADDR_TM_PRT_3D_TILED_THIN1://fall through
2099 case ADDR_TM_PRT_TILED_THICK: //fall through
2100 case ADDR_TM_PRT_2D_TILED_THICK://fall through
2101 case ADDR_TM_PRT_3D_TILED_THICK:
2102 UINT_32 pipeSwizzle;
2103 UINT_32 bankSwizzle;
2104
2105 if (m_configFlags.useCombinedSwizzle)
2106 {
2107 ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
2108 &bankSwizzle, &pipeSwizzle);
2109 }
2110 else
2111 {
2112 pipeSwizzle = pIn->pipeSwizzle;
2113 bankSwizzle = pIn->bankSwizzle;
2114 }
2115
2116 ComputeSurfaceCoordFromAddrMacroTiled(addr,
2117 bitPosition,
2118 bpp,
2119 pitch,
2120 height,
2121 numSamples,
2122 tileMode,
2123 tileBase,
2124 compBits,
2125 microTileType,
2126 ignoreSE,
2127 isDepthSampleOrder,
2128 pipeSwizzle,
2129 bankSwizzle,
2130 pTileInfo,
2131 pX,
2132 pY,
2133 pSlice,
2134 pSample);
2135 break;
2136 default:
2137 ADDR_ASSERT_ALWAYS();
2138 }
2139 }
2140
2141
2142 /**
2143 ***************************************************************************************************
2144 * EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled
2145 *
2146 * @brief
2147 * Compute surface coordinates from address for macro tiled surface
2148 * @return
2149 * N/A
2150 ***************************************************************************************************
2151 */
2152 VOID EgBasedAddrLib::ComputeSurfaceCoordFromAddrMacroTiled(
2153 UINT_64 addr, ///< [in] byte address
2154 UINT_32 bitPosition, ///< [in] bit position
2155 UINT_32 bpp, ///< [in] bits per pixel
2156 UINT_32 pitch, ///< [in] pitch in pixels
2157 UINT_32 height, ///< [in] height in pixels
2158 UINT_32 numSamples, ///< [in] number of samples
2159 AddrTileMode tileMode, ///< [in] tile mode
2160 UINT_32 tileBase, ///< [in] tile base offset
2161 UINT_32 compBits, ///< [in] component bits (for planar surface)
2162 AddrTileType microTileType, ///< [in] micro tiling type
2163 BOOL_32 ignoreSE, ///< [in] TRUE if shader engines can be ignored
2164 BOOL_32 isDepthSampleOrder, ///< [in] TRUE if depth sample order is used
2165 UINT_32 pipeSwizzle, ///< [in] pipe swizzle
2166 UINT_32 bankSwizzle, ///< [in] bank swizzle
2167 ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.
2168 /// **All fields to be valid on entry**
2169 UINT_32* pX, ///< [out] X coord
2170 UINT_32* pY, ///< [out] Y coord
2171 UINT_32* pSlice, ///< [out] slice index
2172 UINT_32* pSample ///< [out] sample index
2173 ) const
2174 {
2175 UINT_32 mx;
2176 UINT_32 my;
2177 UINT_64 tileBits;
2178 UINT_64 macroTileBits;
2179 UINT_32 slices;
2180 UINT_32 tileSlices;
2181 UINT_64 elementOffset;
2182 UINT_64 macroTileIndex;
2183 UINT_32 tileIndex;
2184 UINT_64 totalOffset;
2185
2186
2187 UINT_32 bank;
2188 UINT_32 pipe;
2189 UINT_32 groupBits = m_pipeInterleaveBytes << 3;
2190 UINT_32 pipes = HwlGetPipes(pTileInfo);
2191 UINT_32 banks = pTileInfo->banks;
2192
2193 UINT_32 bankInterleave = m_bankInterleave;
2194
2195 UINT_64 addrBits = BYTES_TO_BITS(addr) + bitPosition;
2196
2197 //
2198 // remove bits for bank and pipe
2199 //
2200 totalOffset = (addrBits % groupBits) +
2201 (((addrBits / groupBits / pipes) % bankInterleave) * groupBits) +
2202 (((addrBits / groupBits / pipes) / bankInterleave) / banks) * groupBits * bankInterleave;
2203
2204 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
2205
2206 UINT_32 microTileBits = bpp * microTileThickness * MicroTilePixels * numSamples;
2207
2208 UINT_32 microTileBytes = BITS_TO_BYTES(microTileBits);
2209 //
2210 // Determine if tiles need to be split across slices.
2211 //
2212 // If the size of the micro tile is larger than the tile split size, then the tile will be
2213 // split across multiple slices.
2214 //
2215 UINT_32 slicesPerTile = 1; //_State->TileSlices
2216
2217 if ((microTileBytes > pTileInfo->tileSplitBytes) && (microTileThickness == 1))
2218 { //don't support for thick mode
2219
2220 //
2221 // Compute the number of slices per tile.
2222 //
2223 slicesPerTile = microTileBytes / pTileInfo->tileSplitBytes;
2224 }
2225
2226 tileBits = microTileBits / slicesPerTile; // micro tile bits
2227
2228 // in micro tiles because not MicroTileWidth timed.
2229 UINT_32 macroWidth = pTileInfo->bankWidth * pipes * pTileInfo->macroAspectRatio;
2230 // in micro tiles as well
2231 UINT_32 macroHeight = pTileInfo->bankHeight * banks / pTileInfo->macroAspectRatio;
2232
2233 UINT_32 pitchInMacroTiles = pitch / MicroTileWidth / macroWidth;
2234
2235 macroTileBits = (macroWidth * macroHeight) * tileBits / (banks * pipes);
2236
2237 macroTileIndex = totalOffset / macroTileBits;
2238
2239 // pitchMacros * height / heightMacros; macroTilesPerSlice == _State->SliceMacros
2240 UINT_32 macroTilesPerSlice = (pitch / (macroWidth * MicroTileWidth)) * height /
2241 (macroHeight * MicroTileWidth);
2242
2243 slices = static_cast<UINT_32>(macroTileIndex / macroTilesPerSlice);
2244
2245 *pSlice = static_cast<UINT_32>(slices / slicesPerTile * microTileThickness);
2246
2247 //
2248 // calculate element offset and x[2:0], y[2:0], z[1:0] for thick
2249 //
2250 tileSlices = slices % slicesPerTile;
2251
2252 elementOffset = tileSlices * tileBits;
2253 elementOffset += totalOffset % tileBits;
2254
2255 UINT_32 coordZ = 0;
2256
2257 HwlComputePixelCoordFromOffset(static_cast<UINT_32>(elementOffset),
2258 bpp,
2259 numSamples,
2260 tileMode,
2261 tileBase,
2262 compBits,
2263 pX,
2264 pY,
2265 &coordZ,
2266 pSample,
2267 microTileType,
2268 isDepthSampleOrder);
2269
2270 macroTileIndex = macroTileIndex % macroTilesPerSlice;
2271 *pY += static_cast<UINT_32>(macroTileIndex / pitchInMacroTiles * macroHeight * MicroTileHeight);
2272 *pX += static_cast<UINT_32>(macroTileIndex % pitchInMacroTiles * macroWidth * MicroTileWidth);
2273
2274 *pSlice += coordZ;
2275
2276 tileIndex = static_cast<UINT_32>((totalOffset % macroTileBits) / tileBits);
2277
2278 my = (tileIndex / pTileInfo->bankWidth) % pTileInfo->bankHeight * MicroTileHeight;
2279 mx = (tileIndex % pTileInfo->bankWidth) * pipes * MicroTileWidth;
2280
2281 *pY += my;
2282 *pX += mx;
2283
2284 bank = ComputeBankFromAddr(addr, banks, pipes);
2285 pipe = ComputePipeFromAddr(addr, pipes);
2286
2287 HwlComputeSurfaceCoord2DFromBankPipe(tileMode,
2288 pX,
2289 pY,
2290 *pSlice,
2291 bank,
2292 pipe,
2293 bankSwizzle,
2294 pipeSwizzle,
2295 tileSlices,
2296 ignoreSE,
2297 pTileInfo);
2298 }
2299
2300 /**
2301 ***************************************************************************************************
2302 * EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe
2303 *
2304 * @brief
2305 * Compute surface x,y coordinates from bank/pipe info
2306 * @return
2307 * N/A
2308 ***************************************************************************************************
2309 */
2310 VOID EgBasedAddrLib::ComputeSurfaceCoord2DFromBankPipe(
2311 AddrTileMode tileMode, ///< [in] tile mode
2312 UINT_32 x, ///< [in] x coordinate
2313 UINT_32 y, ///< [in] y coordinate
2314 UINT_32 slice, ///< [in] slice index
2315 UINT_32 bank, ///< [in] bank number
2316 UINT_32 pipe, ///< [in] pipe number
2317 UINT_32 bankSwizzle,///< [in] bank swizzle
2318 UINT_32 pipeSwizzle,///< [in] pipe swizzle
2319 UINT_32 tileSlices, ///< [in] slices in a micro tile
2320 ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry**
2321 CoordFromBankPipe* pOutput ///< [out] pointer to extracted x/y bits
2322 ) const
2323 {
2324 UINT_32 yBit3 = 0;
2325 UINT_32 yBit4 = 0;
2326 UINT_32 yBit5 = 0;
2327 UINT_32 yBit6 = 0;
2328
2329 UINT_32 xBit3 = 0;
2330 UINT_32 xBit4 = 0;
2331 UINT_32 xBit5 = 0;
2332
2333 UINT_32 tileSplitRotation;
2334
2335 UINT_32 numPipes = HwlGetPipes(pTileInfo);
2336
2337 UINT_32 bankRotation = ComputeBankRotation(tileMode,
2338 pTileInfo->banks, numPipes);
2339
2340 UINT_32 pipeRotation = ComputePipeRotation(tileMode, numPipes);
2341
2342 UINT_32 xBit = x / (MicroTileWidth * pTileInfo->bankWidth * numPipes);
2343 UINT_32 yBit = y / (MicroTileHeight * pTileInfo->bankHeight);
2344
2345 //calculate the bank and pipe before rotation and swizzle
2346
2347 switch (tileMode)
2348 {
2349 case ADDR_TM_2D_TILED_THIN1: //fall through
2350 case ADDR_TM_2D_TILED_THICK: //fall through
2351 case ADDR_TM_2D_TILED_XTHICK: //fall through
2352 case ADDR_TM_3D_TILED_THIN1: //fall through
2353 case ADDR_TM_3D_TILED_THICK: //fall through
2354 case ADDR_TM_3D_TILED_XTHICK:
2355 tileSplitRotation = ((pTileInfo->banks / 2) + 1);
2356 break;
2357 default:
2358 tileSplitRotation = 0;
2359 break;
2360 }
2361
2362 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
2363
2364 bank ^= tileSplitRotation * tileSlices;
2365 if (pipeRotation == 0)
2366 {
2367 bank ^= bankRotation * (slice / microTileThickness) + bankSwizzle;
2368 bank %= pTileInfo->banks;
2369 pipe ^= pipeSwizzle;
2370 }
2371 else
2372 {
2373 bank ^= bankRotation * (slice / microTileThickness) / numPipes + bankSwizzle;
2374 bank %= pTileInfo->banks;
2375 pipe ^= pipeRotation * (slice / microTileThickness) + pipeSwizzle;
2376 }
2377
2378 if (pTileInfo->macroAspectRatio == 1)
2379 {
2380 switch (pTileInfo->banks)
2381 {
2382 case 2:
2383 yBit3 = _BIT(bank, 0) ^ _BIT(xBit,0);
2384 break;
2385 case 4:
2386 yBit4 = _BIT(bank, 0) ^ _BIT(xBit,0);
2387 yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1);
2388 break;
2389 case 8:
2390 yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
2391 yBit5 = _BIT(bank, 0) ^ _BIT(xBit,0);
2392 yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ yBit5;
2393 break;
2394 case 16:
2395 yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3);
2396 yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2);
2397 yBit6 = _BIT(bank, 0) ^ _BIT(xBit, 0);
2398 yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ yBit6;
2399 break;
2400 default:
2401 break;
2402 }
2403
2404 }
2405 else if (pTileInfo->macroAspectRatio == 2)
2406 {
2407 switch (pTileInfo->banks)
2408 {
2409 case 2: //xBit3 = yBit3^b0
2410 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,0);
2411 break;
2412 case 4: //xBit3=yBit4^b0; yBit3=xBit4^b1
2413 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1);
2414 yBit3 = _BIT(bank, 1) ^ _BIT(xBit,1);
2415 break;
2416 case 8: //xBit4, xBit5, yBit5 are known
2417 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2);
2418 yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
2419 yBit4 = _BIT(bank, 1) ^ _BIT(xBit,1) ^ _BIT(yBit, 2);
2420 break;
2421 case 16://x4,x5,x6,y6 are known
2422 xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3); //x3 = y6 ^ b0
2423 yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3
2424 yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = x5 ^ b2
2425 yBit5 = _BIT(bank, 1) ^ _BIT(xBit, 1) ^ _BIT(yBit, 3); //y5=x4^y6^b1
2426 break;
2427 default:
2428 break;
2429 }
2430 }
2431 else if (pTileInfo->macroAspectRatio == 4)
2432 {
2433 switch (pTileInfo->banks)
2434 {
2435 case 4: //yBit3, yBit4
2436 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,1);
2437 xBit4 = _BIT(bank, 1) ^ _BIT(yBit,0);
2438 break;
2439 case 8: //xBit5, yBit4, yBit5
2440 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2);
2441 yBit3 = _BIT(bank, 2) ^ _BIT(xBit,2);
2442 xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit,2);
2443 break;
2444 case 16: //xBit5, xBit6, yBit5, yBit6
2445 xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = b0 ^ y6
2446 xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = b1 ^ y5 ^ y6;
2447 yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = b3 ^ x6;
2448 yBit4 = _BIT(bank, 2) ^ _BIT(xBit, 2); //y4 = b2 ^ x5;
2449 break;
2450 default:
2451 break;
2452 }
2453 }
2454 else if (pTileInfo->macroAspectRatio == 8)
2455 {
2456 switch (pTileInfo->banks)
2457 {
2458 case 8: //yBit3, yBit4, yBit5
2459 xBit3 = _BIT(bank, 0) ^ _BIT(yBit,2); //x3 = b0 ^ y5;
2460 xBit4 = _BIT(bank, 1) ^ _BIT(yBit,1) ^ _BIT(yBit, 2);//x4 = b1 ^ y4 ^ y5;
2461 xBit5 = _BIT(bank, 2) ^ _BIT(yBit,0);
2462 break;
2463 case 16: //xBit6, yBit4, yBit5, yBit6
2464 xBit3 = _BIT(bank, 0) ^ _BIT(yBit, 3);//x3 = y6 ^ b0
2465 xBit4 = _BIT(bank, 1) ^ _BIT(yBit, 2) ^ _BIT(yBit, 3);//x4 = y5 ^ y6 ^ b1
2466 xBit5 = _BIT(bank, 2) ^ _BIT(yBit, 1);//x5 = y4 ^ b2
2467 yBit3 = _BIT(bank, 3) ^ _BIT(xBit, 3); //y3 = x6 ^ b3
2468 break;
2469 default:
2470 break;
2471 }
2472 }
2473
2474 pOutput->xBits = xBit;
2475 pOutput->yBits = yBit;
2476
2477 pOutput->xBit3 = xBit3;
2478 pOutput->xBit4 = xBit4;
2479 pOutput->xBit5 = xBit5;
2480 pOutput->yBit3 = yBit3;
2481 pOutput->yBit4 = yBit4;
2482 pOutput->yBit5 = yBit5;
2483 pOutput->yBit6 = yBit6;
2484 }
2485
2486 /**
2487 ***************************************************************************************************
2488 * EgBasedAddrLib::HwlExtractBankPipeSwizzle
2489 * @brief
2490 * Entry of EgBasedAddrLib ExtractBankPipeSwizzle
2491 * @return
2492 * ADDR_E_RETURNCODE
2493 ***************************************************************************************************
2494 */
2495 ADDR_E_RETURNCODE EgBasedAddrLib::HwlExtractBankPipeSwizzle(
2496 const ADDR_EXTRACT_BANKPIPE_SWIZZLE_INPUT* pIn, ///< [in] input structure
2497 ADDR_EXTRACT_BANKPIPE_SWIZZLE_OUTPUT* pOut ///< [out] output structure
2498 ) const
2499 {
2500 ExtractBankPipeSwizzle(pIn->base256b,
2501 pIn->pTileInfo,
2502 &pOut->bankSwizzle,
2503 &pOut->pipeSwizzle);
2504
2505 return ADDR_OK;
2506 }
2507
2508
2509 /**
2510 ***************************************************************************************************
2511 * EgBasedAddrLib::HwlCombineBankPipeSwizzle
2512 * @brief
2513 * Combine bank/pipe swizzle
2514 * @return
2515 * ADDR_E_RETURNCODE
2516 ***************************************************************************************************
2517 */
2518 ADDR_E_RETURNCODE EgBasedAddrLib::HwlCombineBankPipeSwizzle(
2519 UINT_32 bankSwizzle, ///< [in] bank swizzle
2520 UINT_32 pipeSwizzle, ///< [in] pipe swizzle
2521 ADDR_TILEINFO* pTileInfo, ///< [in] tile info
2522 UINT_64 baseAddr, ///< [in] base address
2523 UINT_32* pTileSwizzle ///< [out] combined swizzle
2524 ) const
2525 {
2526 ADDR_E_RETURNCODE retCode = ADDR_OK;
2527
2528 if (pTileSwizzle)
2529 {
2530 *pTileSwizzle = GetBankPipeSwizzle(bankSwizzle, pipeSwizzle, baseAddr, pTileInfo);
2531 }
2532 else
2533 {
2534 retCode = ADDR_INVALIDPARAMS;
2535 }
2536
2537 return retCode;
2538 }
2539
2540 /**
2541 ***************************************************************************************************
2542 * EgBasedAddrLib::HwlComputeBaseSwizzle
2543 * @brief
2544 * Compute base swizzle
2545 * @return
2546 * ADDR_E_RETURNCODE
2547 ***************************************************************************************************
2548 */
2549 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeBaseSwizzle(
2550 const ADDR_COMPUTE_BASE_SWIZZLE_INPUT* pIn,
2551 ADDR_COMPUTE_BASE_SWIZZLE_OUTPUT* pOut
2552 ) const
2553 {
2554 UINT_32 bankSwizzle = 0;
2555 UINT_32 pipeSwizzle = 0;
2556 ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
2557
2558 ADDR_ASSERT(IsMacroTiled(pIn->tileMode));
2559 ADDR_ASSERT(pIn->pTileInfo);
2560
2561 /// This is a legacy misreading of h/w doc, use it as it doesn't hurt.
2562 static const UINT_8 bankRotationArray[4][16] = {
2563 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_2_BANK
2564 { 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_4_BANK
2565 { 0, 3, 6, 1, 4, 7, 2, 5, 0, 0, 0, 0, 0, 0, 0, 0 }, // ADDR_SURF_8_BANK
2566 { 0, 7, 14, 5, 12, 3, 10, 1, 8, 15, 6, 13, 4, 11, 2, 9 }, // ADDR_SURF_16_BANK
2567 };
2568
2569 UINT_32 banks = pTileInfo ? pTileInfo->banks : 2;
2570 UINT_32 hwNumBanks;
2571
2572 // Uses less bank swizzle bits
2573 if (pIn->option.reduceBankBit && banks > 2)
2574 {
2575 banks >>= 1;
2576 }
2577
2578 switch (banks)
2579 {
2580 case 2:
2581 hwNumBanks = 0;
2582 break;
2583 case 4:
2584 hwNumBanks = 1;
2585 break;
2586 case 8:
2587 hwNumBanks = 2;
2588 break;
2589 case 16:
2590 hwNumBanks = 3;
2591 break;
2592 default:
2593 ADDR_ASSERT_ALWAYS();
2594 hwNumBanks = 0;
2595 break;
2596 }
2597
2598 if (pIn->option.genOption == ADDR_SWIZZLE_GEN_LINEAR)
2599 {
2600 bankSwizzle = pIn->surfIndex & (banks - 1);
2601 }
2602 else // (pIn->option.genOption == ADDR_SWIZZLE_GEN_DEFAULT)
2603 {
2604 bankSwizzle = bankRotationArray[hwNumBanks][pIn->surfIndex & (banks - 1)];
2605 }
2606
2607 if (IsMacro3dTiled(pIn->tileMode))
2608 {
2609 pipeSwizzle = pIn->surfIndex & (HwlGetPipes(pTileInfo) - 1);
2610 }
2611
2612 return HwlCombineBankPipeSwizzle(bankSwizzle, pipeSwizzle, pTileInfo, 0, &pOut->tileSwizzle);
2613 }
2614
2615 /**
2616 ***************************************************************************************************
2617 * EgBasedAddrLib::ExtractBankPipeSwizzle
2618 * @brief
2619 * Extract bank/pipe swizzle from base256b
2620 * @return
2621 * N/A
2622 ***************************************************************************************************
2623 */
2624 VOID EgBasedAddrLib::ExtractBankPipeSwizzle(
2625 UINT_32 base256b, ///< [in] input base256b register value
2626 ADDR_TILEINFO* pTileInfo, ///< [in] 2D tile parameters. Client must provide all data
2627 UINT_32* pBankSwizzle, ///< [out] bank swizzle
2628 UINT_32* pPipeSwizzle ///< [out] pipe swizzle
2629 ) const
2630 {
2631 UINT_32 bankSwizzle = 0;
2632 UINT_32 pipeSwizzle = 0;
2633
2634 if (base256b != 0)
2635 {
2636 UINT_32 numPipes = HwlGetPipes(pTileInfo);
2637 UINT_32 bankBits = QLog2(pTileInfo->banks);
2638 UINT_32 pipeBits = QLog2(numPipes);
2639 UINT_32 groupBytes = m_pipeInterleaveBytes;
2640 UINT_32 bankInterleave = m_bankInterleave;
2641
2642 pipeSwizzle =
2643 (base256b / (groupBytes >> 8)) & ((1<<pipeBits)-1);
2644
2645 bankSwizzle =
2646 (base256b / (groupBytes >> 8) / numPipes / bankInterleave) & ((1 << bankBits) - 1);
2647 }
2648
2649 *pPipeSwizzle = pipeSwizzle;
2650 *pBankSwizzle = bankSwizzle;
2651 }
2652
2653 /**
2654 ***************************************************************************************************
2655 * EgBasedAddrLib::GetBankPipeSwizzle
2656 * @brief
2657 * Combine bank/pipe swizzle
2658 * @return
2659 * Base256b bits (only filled bank/pipe bits)
2660 ***************************************************************************************************
2661 */
2662 UINT_32 EgBasedAddrLib::GetBankPipeSwizzle(
2663 UINT_32 bankSwizzle, ///< [in] bank swizzle
2664 UINT_32 pipeSwizzle, ///< [in] pipe swizzle
2665 UINT_64 baseAddr, ///< [in] base address
2666 ADDR_TILEINFO* pTileInfo ///< [in] tile info
2667 ) const
2668 {
2669 UINT_32 pipeBits = QLog2(HwlGetPipes(pTileInfo));
2670 UINT_32 bankInterleaveBits = QLog2(m_bankInterleave);
2671 UINT_32 tileSwizzle = pipeSwizzle + ((bankSwizzle << bankInterleaveBits) << pipeBits);
2672
2673 baseAddr ^= tileSwizzle * m_pipeInterleaveBytes;
2674 baseAddr >>= 8;
2675
2676 return static_cast<UINT_32>(baseAddr);
2677 }
2678
2679 /**
2680 ***************************************************************************************************
2681 * EgBasedAddrLib::ComputeSliceTileSwizzle
2682 * @brief
2683 * Compute cubemap/3d texture faces/slices tile swizzle
2684 * @return
2685 * Tile swizzle
2686 ***************************************************************************************************
2687 */
2688 UINT_32 EgBasedAddrLib::ComputeSliceTileSwizzle(
2689 AddrTileMode tileMode, ///< [in] Tile mode
2690 UINT_32 baseSwizzle, ///< [in] Base swizzle
2691 UINT_32 slice, ///< [in] Slice index, Cubemap face index, 0 means +X
2692 UINT_64 baseAddr, ///< [in] Base address
2693 ADDR_TILEINFO* pTileInfo ///< [in] Bank structure
2694 ) const
2695 {
2696 UINT_32 tileSwizzle = 0;
2697
2698 if (IsMacroTiled(tileMode)) // Swizzle only for macro tile mode
2699 {
2700 UINT_32 firstSlice = slice / ComputeSurfaceThickness(tileMode);
2701
2702 UINT_32 numPipes = HwlGetPipes(pTileInfo);
2703 UINT_32 numBanks = pTileInfo->banks;
2704
2705 UINT_32 pipeRotation;
2706 UINT_32 bankRotation;
2707
2708 UINT_32 bankSwizzle = 0;
2709 UINT_32 pipeSwizzle = 0;
2710
2711 pipeRotation = ComputePipeRotation(tileMode, numPipes);
2712 bankRotation = ComputeBankRotation(tileMode, numBanks, numPipes);
2713
2714 if (baseSwizzle != 0)
2715 {
2716 ExtractBankPipeSwizzle(baseSwizzle,
2717 pTileInfo,
2718 &bankSwizzle,
2719 &pipeSwizzle);
2720 }
2721
2722 if (pipeRotation == 0) //2D mode
2723 {
2724 bankSwizzle += firstSlice * bankRotation;
2725 bankSwizzle %= numBanks;
2726 }
2727 else //3D mode
2728 {
2729 pipeSwizzle += firstSlice * pipeRotation;
2730 pipeSwizzle %= numPipes;
2731 bankSwizzle += firstSlice * bankRotation / numPipes;
2732 bankSwizzle %= numBanks;
2733 }
2734
2735 tileSwizzle = GetBankPipeSwizzle(bankSwizzle,
2736 pipeSwizzle,
2737 baseAddr,
2738 pTileInfo);
2739 }
2740
2741 return tileSwizzle;
2742 }
2743
2744 /**
2745 ***************************************************************************************************
2746 * EgBasedAddrLib::HwlComputeQbStereoRightSwizzle
2747 *
2748 * @brief
2749 * Compute right eye swizzle
2750 * @return
2751 * swizzle
2752 ***************************************************************************************************
2753 */
2754 UINT_32 EgBasedAddrLib::HwlComputeQbStereoRightSwizzle(
2755 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pInfo ///< [in] Surface info, must be valid
2756 ) const
2757 {
2758 UINT_32 bankBits = 0;
2759 UINT_32 swizzle = 0;
2760
2761 // The assumption is default swizzle for left eye is 0
2762 if (IsMacroTiled(pInfo->tileMode) && pInfo->pStereoInfo && pInfo->pTileInfo)
2763 {
2764 bankBits = ComputeBankFromCoord(0, pInfo->height, 0,
2765 pInfo->tileMode, 0, 0, pInfo->pTileInfo);
2766
2767 if (bankBits)
2768 {
2769 HwlCombineBankPipeSwizzle(bankBits, 0, pInfo->pTileInfo, 0, &swizzle);
2770 }
2771 }
2772
2773 return swizzle;
2774 }
2775
2776 /**
2777 ***************************************************************************************************
2778 * EgBasedAddrLib::ComputeBankFromCoord
2779 *
2780 * @brief
2781 * Compute bank number from coordinates
2782 * @return
2783 * Bank number
2784 ***************************************************************************************************
2785 */
2786 UINT_32 EgBasedAddrLib::ComputeBankFromCoord(
2787 UINT_32 x, ///< [in] x coordinate
2788 UINT_32 y, ///< [in] y coordinate
2789 UINT_32 slice, ///< [in] slice index
2790 AddrTileMode tileMode, ///< [in] tile mode
2791 UINT_32 bankSwizzle, ///< [in] bank swizzle
2792 UINT_32 tileSplitSlice, ///< [in] If the size of the pixel offset is larger than the
2793 /// tile split size, then the pixel will be moved to a separate
2794 /// slice. This value equals pixelOffset / tileSplitBytes
2795 /// in this case. Otherwise this is 0.
2796 ADDR_TILEINFO* pTileInfo ///< [in] tile info
2797 ) const
2798 {
2799 UINT_32 pipes = HwlGetPipes(pTileInfo);
2800 UINT_32 bankBit0 = 0;
2801 UINT_32 bankBit1 = 0;
2802 UINT_32 bankBit2 = 0;
2803 UINT_32 bankBit3 = 0;
2804 UINT_32 sliceRotation;
2805 UINT_32 tileSplitRotation;
2806 UINT_32 bank;
2807 UINT_32 numBanks = pTileInfo->banks;
2808 UINT_32 bankWidth = pTileInfo->bankWidth;
2809 UINT_32 bankHeight = pTileInfo->bankHeight;
2810
2811 UINT_32 tx = x / MicroTileWidth / (bankWidth * pipes);
2812 UINT_32 ty = y / MicroTileHeight / bankHeight;
2813
2814 UINT_32 x3 = _BIT(tx,0);
2815 UINT_32 x4 = _BIT(tx,1);
2816 UINT_32 x5 = _BIT(tx,2);
2817 UINT_32 x6 = _BIT(tx,3);
2818 UINT_32 y3 = _BIT(ty,0);
2819 UINT_32 y4 = _BIT(ty,1);
2820 UINT_32 y5 = _BIT(ty,2);
2821 UINT_32 y6 = _BIT(ty,3);
2822
2823 switch (numBanks)
2824 {
2825 case 16:
2826 bankBit0 = x3 ^ y6;
2827 bankBit1 = x4 ^ y5 ^ y6;
2828 bankBit2 = x5 ^ y4;
2829 bankBit3 = x6 ^ y3;
2830 break;
2831 case 8:
2832 bankBit0 = x3 ^ y5;
2833 bankBit1 = x4 ^ y4 ^ y5;
2834 bankBit2 = x5 ^ y3;
2835 break;
2836 case 4:
2837 bankBit0 = x3 ^ y4;
2838 bankBit1 = x4 ^ y3;
2839 break;
2840 case 2:
2841 bankBit0 = x3 ^ y3;
2842 break;
2843 default:
2844 ADDR_ASSERT_ALWAYS();
2845 break;
2846 }
2847
2848 bank = bankBit0 | (bankBit1 << 1) | (bankBit2 << 2) | (bankBit3 << 3);
2849
2850 //Bits2Number(4, bankBit3, bankBit2, bankBit1, bankBit0);
2851
2852 bank = HwlPreAdjustBank((x / MicroTileWidth), bank, pTileInfo);
2853 //
2854 // Compute bank rotation for the slice.
2855 //
2856 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
2857
2858 switch (tileMode)
2859 {
2860 case ADDR_TM_2D_TILED_THIN1: // fall through
2861 case ADDR_TM_2D_TILED_THICK: // fall through
2862 case ADDR_TM_2D_TILED_XTHICK:
2863 sliceRotation = ((numBanks / 2) - 1) * (slice / microTileThickness);
2864 break;
2865 case ADDR_TM_3D_TILED_THIN1: // fall through
2866 case ADDR_TM_3D_TILED_THICK: // fall through
2867 case ADDR_TM_3D_TILED_XTHICK:
2868 sliceRotation =
2869 Max(1u, (pipes / 2) - 1) * (slice / microTileThickness) / pipes;
2870 break;
2871 default:
2872 sliceRotation = 0;
2873 break;
2874 }
2875
2876
2877 //
2878 // Compute bank rotation for the tile split slice.
2879 //
2880 // The sample slice will be non-zero if samples must be split across multiple slices.
2881 // This situation arises when the micro tile size multiplied yBit the number of samples exceeds
2882 // the split size (set in GB_ADDR_CONFIG).
2883 //
2884 switch (tileMode)
2885 {
2886 case ADDR_TM_2D_TILED_THIN1: //fall through
2887 case ADDR_TM_3D_TILED_THIN1: //fall through
2888 case ADDR_TM_PRT_2D_TILED_THIN1: //fall through
2889 case ADDR_TM_PRT_3D_TILED_THIN1: //fall through
2890 tileSplitRotation = ((numBanks / 2) + 1) * tileSplitSlice;
2891 break;
2892 default:
2893 tileSplitRotation = 0;
2894 break;
2895 }
2896
2897 //
2898 // Apply bank rotation for the slice and tile split slice.
2899 //
2900 bank ^= bankSwizzle + sliceRotation;
2901 bank ^= tileSplitRotation;
2902
2903 bank &= (numBanks - 1);
2904
2905 return bank;
2906 }
2907
2908 /**
2909 ***************************************************************************************************
2910 * EgBasedAddrLib::ComputeBankFromAddr
2911 *
2912 * @brief
2913 * Compute the bank number from an address
2914 * @return
2915 * Bank number
2916 ***************************************************************************************************
2917 */
2918 UINT_32 EgBasedAddrLib::ComputeBankFromAddr(
2919 UINT_64 addr, ///< [in] address
2920 UINT_32 numBanks, ///< [in] number of banks
2921 UINT_32 numPipes ///< [in] number of pipes
2922 ) const
2923 {
2924 UINT_32 bank;
2925
2926 //
2927 // The LSBs of the address are arranged as follows:
2928 // bank | bankInterleave | pipe | pipeInterleave
2929 //
2930 // To get the bank number, shift off the pipe interleave, pipe, and bank interlave bits and
2931 // mask the bank bits.
2932 //
2933 bank = static_cast<UINT_32>(
2934 (addr >> Log2(m_pipeInterleaveBytes * numPipes * m_bankInterleave)) &
2935 (numBanks - 1)
2936 );
2937
2938 return bank;
2939 }
2940
2941 /**
2942 ***************************************************************************************************
2943 * EgBasedAddrLib::ComputePipeRotation
2944 *
2945 * @brief
2946 * Compute pipe rotation value
2947 * @return
2948 * Pipe rotation
2949 ***************************************************************************************************
2950 */
2951 UINT_32 EgBasedAddrLib::ComputePipeRotation(
2952 AddrTileMode tileMode, ///< [in] tile mode
2953 UINT_32 numPipes ///< [in] number of pipes
2954 ) const
2955 {
2956 UINT_32 rotation;
2957
2958 switch (tileMode)
2959 {
2960 case ADDR_TM_3D_TILED_THIN1: //fall through
2961 case ADDR_TM_3D_TILED_THICK: //fall through
2962 case ADDR_TM_3D_TILED_XTHICK: //fall through
2963 case ADDR_TM_PRT_3D_TILED_THIN1: //fall through
2964 case ADDR_TM_PRT_3D_TILED_THICK:
2965 rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1);
2966 break;
2967 default:
2968 rotation = 0;
2969 }
2970
2971 return rotation;
2972 }
2973
2974
2975
2976 /**
2977 ***************************************************************************************************
2978 * EgBasedAddrLib::ComputeBankRotation
2979 *
2980 * @brief
2981 * Compute bank rotation value
2982 * @return
2983 * Bank rotation
2984 ***************************************************************************************************
2985 */
2986 UINT_32 EgBasedAddrLib::ComputeBankRotation(
2987 AddrTileMode tileMode, ///< [in] tile mode
2988 UINT_32 numBanks, ///< [in] number of banks
2989 UINT_32 numPipes ///< [in] number of pipes
2990 ) const
2991 {
2992 UINT_32 rotation;
2993
2994 switch (tileMode)
2995 {
2996 case ADDR_TM_2D_TILED_THIN1: // fall through
2997 case ADDR_TM_2D_TILED_THICK: // fall through
2998 case ADDR_TM_2D_TILED_XTHICK:
2999 case ADDR_TM_PRT_2D_TILED_THIN1:
3000 case ADDR_TM_PRT_2D_TILED_THICK:
3001 // Rotate banks per Z-slice yBit 1 for 4-bank or 3 for 8-bank
3002 rotation = numBanks / 2 - 1;
3003 break;
3004 case ADDR_TM_3D_TILED_THIN1: // fall through
3005 case ADDR_TM_3D_TILED_THICK: // fall through
3006 case ADDR_TM_3D_TILED_XTHICK:
3007 case ADDR_TM_PRT_3D_TILED_THIN1:
3008 case ADDR_TM_PRT_3D_TILED_THICK:
3009 rotation = (numPipes < 4) ? 1 : (numPipes / 2 - 1); // rotate pipes & banks
3010 break;
3011 default:
3012 rotation = 0;
3013 }
3014
3015 return rotation;
3016 }
3017
3018
3019 /**
3020 ***************************************************************************************************
3021 * EgBasedAddrLib::ComputeHtileBytes
3022 *
3023 * @brief
3024 * Compute htile size in bytes
3025 *
3026 * @return
3027 * Htile size in bytes
3028 ***************************************************************************************************
3029 */
3030 UINT_64 EgBasedAddrLib::ComputeHtileBytes(
3031 UINT_32 pitch, ///< [in] pitch
3032 UINT_32 height, ///< [in] height
3033 UINT_32 bpp, ///< [in] bits per pixel
3034 BOOL_32 isLinear, ///< [in] if it is linear mode
3035 UINT_32 numSlices, ///< [in] number of slices
3036 UINT_64* sliceBytes, ///< [out] bytes per slice
3037 UINT_32 baseAlign ///< [in] base alignments
3038 ) const
3039 {
3040 UINT_64 surfBytes;
3041
3042 const UINT_64 HtileCacheLineSize = BITS_TO_BYTES(HtileCacheBits);
3043
3044 *sliceBytes = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp / 64);
3045
3046 if (m_configFlags.useHtileSliceAlign)
3047 {
3048 // Align the sliceSize to htilecachelinesize * pipes at first
3049 *sliceBytes = PowTwoAlign(*sliceBytes, HtileCacheLineSize * m_pipes);
3050 surfBytes = *sliceBytes * numSlices;
3051 }
3052 else
3053 {
3054 // Align the surfSize to htilecachelinesize * pipes at last
3055 surfBytes = *sliceBytes * numSlices;
3056 surfBytes = PowTwoAlign(surfBytes, HtileCacheLineSize * m_pipes);
3057 }
3058
3059 return surfBytes;
3060 }
3061
3062 /**
3063 ***************************************************************************************************
3064 * EgBasedAddrLib::DispatchComputeFmaskInfo
3065 *
3066 * @brief
3067 * Compute fmask sizes include padded pitch, height, slices, total size in bytes,
3068 * meanwhile output suitable tile mode and alignments as well. Results are returned
3069 * through output parameters.
3070 *
3071 * @return
3072 * ADDR_E_RETURNCODE
3073 ***************************************************************************************************
3074 */
3075 ADDR_E_RETURNCODE EgBasedAddrLib::DispatchComputeFmaskInfo(
3076 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
3077 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut) ///< [out] output structure
3078 {
3079 ADDR_E_RETURNCODE retCode = ADDR_OK;
3080
3081 ADDR_COMPUTE_SURFACE_INFO_INPUT surfIn = {0};
3082 ADDR_COMPUTE_SURFACE_INFO_OUTPUT surfOut = {0};
3083
3084 // Setup input structure
3085 surfIn.tileMode = pIn->tileMode;
3086 surfIn.width = pIn->pitch;
3087 surfIn.height = pIn->height;
3088 surfIn.numSlices = pIn->numSlices;
3089 surfIn.pTileInfo = pIn->pTileInfo;
3090 surfIn.tileType = ADDR_NON_DISPLAYABLE;
3091 surfIn.flags.fmask = 1;
3092
3093 // Setup output structure
3094 surfOut.pTileInfo = pOut->pTileInfo;
3095
3096 // Setup hwl specific fields
3097 HwlFmaskPreThunkSurfInfo(pIn, pOut, &surfIn, &surfOut);
3098
3099 surfIn.bpp = HwlComputeFmaskBits(pIn, &surfIn.numSamples);
3100
3101 // ComputeSurfaceInfo needs numSamples in surfOut as surface routines need adjusted numSamples
3102 surfOut.numSamples = surfIn.numSamples;
3103
3104 retCode = HwlComputeSurfaceInfo(&surfIn, &surfOut);
3105
3106 // Save bpp field for surface dump support
3107 surfOut.bpp = surfIn.bpp;
3108
3109 if (retCode == ADDR_OK)
3110 {
3111 pOut->bpp = surfOut.bpp;
3112 pOut->pitch = surfOut.pitch;
3113 pOut->height = surfOut.height;
3114 pOut->numSlices = surfOut.depth;
3115 pOut->fmaskBytes = surfOut.surfSize;
3116 pOut->baseAlign = surfOut.baseAlign;
3117 pOut->pitchAlign = surfOut.pitchAlign;
3118 pOut->heightAlign = surfOut.heightAlign;
3119
3120 if (surfOut.depth > 1)
3121 {
3122 // For fmask, expNumSlices is stored in depth.
3123 pOut->sliceSize = surfOut.surfSize / surfOut.depth;
3124 }
3125 else
3126 {
3127 pOut->sliceSize = surfOut.surfSize;
3128 }
3129
3130 // Save numSamples field for surface dump support
3131 pOut->numSamples = surfOut.numSamples;
3132
3133 HwlFmaskPostThunkSurfInfo(&surfOut, pOut);
3134 }
3135
3136 return retCode;
3137 }
3138
3139 /**
3140 ***************************************************************************************************
3141 * EgBasedAddrLib::HwlFmaskSurfaceInfo
3142 * @brief
3143 * Entry of EgBasedAddrLib ComputeFmaskInfo
3144 * @return
3145 * ADDR_E_RETURNCODE
3146 ***************************************************************************************************
3147 */
3148 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskInfo(
3149 const ADDR_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
3150 ADDR_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
3151 )
3152 {
3153 ADDR_E_RETURNCODE retCode = ADDR_OK;
3154
3155 ADDR_TILEINFO tileInfo = {0};
3156
3157 // Use internal tile info if pOut does not have a valid pTileInfo
3158 if (pOut->pTileInfo == NULL)
3159 {
3160 pOut->pTileInfo = &tileInfo;
3161 }
3162
3163 retCode = DispatchComputeFmaskInfo(pIn, pOut);
3164
3165 if (retCode == ADDR_OK)
3166 {
3167 pOut->tileIndex =
3168 HwlPostCheckTileIndex(pOut->pTileInfo, pIn->tileMode, ADDR_NON_DISPLAYABLE,
3169 pOut->tileIndex);
3170 }
3171
3172 // Resets pTileInfo to NULL if the internal tile info is used
3173 if (pOut->pTileInfo == &tileInfo)
3174 {
3175 pOut->pTileInfo = NULL;
3176 }
3177
3178 return retCode;
3179 }
3180
3181 /**
3182 ***************************************************************************************************
3183 * EgBasedAddrLib::HwlComputeFmaskAddrFromCoord
3184 * @brief
3185 * Entry of EgBasedAddrLib ComputeFmaskAddrFromCoord
3186 * @return
3187 * ADDR_E_RETURNCODE
3188 ***************************************************************************************************
3189 */
3190 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskAddrFromCoord(
3191 const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
3192 ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
3193 ) const
3194 {
3195 ADDR_E_RETURNCODE retCode = ADDR_OK;
3196
3197 #if ADDR_AM_BUILD
3198 if ((pIn->x > pIn->pitch) ||
3199 (pIn->y > pIn->height) ||
3200 (pIn->numSamples > m_maxSamples) ||
3201 (pIn->sample >= m_maxSamples))
3202 {
3203 retCode = ADDR_INVALIDPARAMS;
3204 }
3205 else
3206 {
3207 pOut->addr = DispatchComputeFmaskAddrFromCoord(pIn, pOut);
3208 }
3209 #endif
3210
3211 return retCode;
3212 }
3213
3214 /**
3215 ***************************************************************************************************
3216 * EgBasedAddrLib::HwlComputeFmaskCoordFromAddr
3217 * @brief
3218 * Entry of EgBasedAddrLib ComputeFmaskCoordFromAddr
3219 * @return
3220 * ADDR_E_RETURNCODE
3221 ***************************************************************************************************
3222 */
3223 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeFmaskCoordFromAddr(
3224 const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
3225 ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
3226 ) const
3227 {
3228 ADDR_E_RETURNCODE retCode = ADDR_OK;
3229
3230 #if ADDR_AM_BUILD
3231 if ((pIn->bitPosition >= 8) ||
3232 (pIn->numSamples > m_maxSamples))
3233 {
3234 retCode = ADDR_INVALIDPARAMS;
3235 }
3236 else
3237 {
3238 DispatchComputeFmaskCoordFromAddr(pIn, pOut);
3239 }
3240 #endif
3241
3242 return retCode;
3243 }
3244
3245 #if ADDR_AM_BUILD
3246 /**
3247 ***************************************************************************************************
3248 * EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord
3249 *
3250 * @brief
3251 * Computes the FMASK address and bit position from a coordinate.
3252 * @return
3253 * The byte address
3254 ***************************************************************************************************
3255 */
3256 UINT_64 EgBasedAddrLib::DispatchComputeFmaskAddrFromCoord(
3257 const ADDR_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
3258 ADDR_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
3259 ) const
3260 {
3261 UINT_32 x = pIn->x;
3262 UINT_32 y = pIn->y;
3263 UINT_32 slice = pIn->slice;
3264 UINT_32 sample = pIn->sample;
3265 UINT_32 plane = pIn->plane;
3266 UINT_32 pitch = pIn->pitch;
3267 UINT_32 height = pIn->height;
3268 UINT_32 numSamples = pIn->numSamples;
3269 AddrTileMode tileMode = pIn->tileMode;
3270 BOOL_32 ignoreSE = pIn->ignoreSE;
3271 ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
3272 BOOL_32 resolved = pIn->resolved;
3273
3274 UINT_32* pBitPosition = &pOut->bitPosition;
3275 UINT_64 addr = 0;
3276
3277 ADDR_ASSERT(numSamples > 1);
3278 ADDR_ASSERT(ComputeSurfaceThickness(tileMode) == 1);
3279
3280 switch (tileMode)
3281 {
3282 case ADDR_TM_1D_TILED_THIN1:
3283 addr = ComputeFmaskAddrFromCoordMicroTiled(x,
3284 y,
3285 slice,
3286 sample,
3287 plane,
3288 pitch,
3289 height,
3290 numSamples,
3291 tileMode,
3292 resolved,
3293 pBitPosition);
3294 break;
3295 case ADDR_TM_2D_TILED_THIN1: //fall through
3296 case ADDR_TM_3D_TILED_THIN1:
3297 UINT_32 pipeSwizzle;
3298 UINT_32 bankSwizzle;
3299
3300 if (m_configFlags.useCombinedSwizzle)
3301 {
3302 ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
3303 &bankSwizzle, &pipeSwizzle);
3304 }
3305 else
3306 {
3307 pipeSwizzle = pIn->pipeSwizzle;
3308 bankSwizzle = pIn->bankSwizzle;
3309 }
3310
3311 addr = ComputeFmaskAddrFromCoordMacroTiled(x,
3312 y,
3313 slice,
3314 sample,
3315 plane,
3316 pitch,
3317 height,
3318 numSamples,
3319 tileMode,
3320 pipeSwizzle,
3321 bankSwizzle,
3322 ignoreSE,
3323 pTileInfo,
3324 resolved,
3325 pBitPosition);
3326 break;
3327 default:
3328 *pBitPosition = 0;
3329 break;
3330 }
3331
3332 return addr;
3333 }
3334
3335 /**
3336 ***************************************************************************************************
3337 * EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled
3338 *
3339 * @brief
3340 * Computes the FMASK address and bit position from a coordinate for 1D tilied (micro
3341 * tiled)
3342 * @return
3343 * The byte address
3344 ***************************************************************************************************
3345 */
3346 UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMicroTiled(
3347 UINT_32 x, ///< [in] x coordinate
3348 UINT_32 y, ///< [in] y coordinate
3349 UINT_32 slice, ///< [in] slice index
3350 UINT_32 sample, ///< [in] sample number
3351 UINT_32 plane, ///< [in] plane number
3352 UINT_32 pitch, ///< [in] surface pitch in pixels
3353 UINT_32 height, ///< [in] surface height in pixels
3354 UINT_32 numSamples, ///< [in] number of samples
3355 AddrTileMode tileMode, ///< [in] tile mode
3356 BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask
3357 UINT_32* pBitPosition ///< [out] pointer to returned bit position
3358 ) const
3359 {
3360 UINT_64 addr = 0;
3361 UINT_32 effectiveBpp;
3362 UINT_32 effectiveSamples;
3363
3364 //
3365 // 2xAA use the same layout as 4xAA
3366 //
3367 if (numSamples == 2)
3368 {
3369 numSamples = 4;
3370 }
3371
3372 //
3373 // Compute the number of planes.
3374 //
3375 if (!resolved)
3376 {
3377 effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3378 effectiveBpp = numSamples;
3379
3380 //
3381 // Compute the address just like a color surface with numSamples bits per element and
3382 // numPlanes samples.
3383 //
3384 addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
3385 y,
3386 slice,
3387 plane, // sample
3388 effectiveBpp,
3389 pitch,
3390 height,
3391 effectiveSamples,
3392 tileMode,
3393 ADDR_NON_DISPLAYABLE,
3394 FALSE,
3395 pBitPosition);
3396
3397 //
3398 // Compute the real bit position. Each (sample, plane) is stored with one bit per sample.
3399 //
3400
3401 //
3402 // Compute the pixel index with in the micro tile
3403 //
3404 UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x % 8,
3405 y % 8,
3406 slice,
3407 1,
3408 tileMode,
3409 ADDR_NON_DISPLAYABLE);
3410
3411 *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1);
3412
3413 UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition;
3414
3415 addr = bitAddr / 8;
3416 }
3417 else
3418 {
3419 effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3420 effectiveSamples = 1;
3421
3422 //
3423 // Compute the address just like a color surface with numSamples bits per element and
3424 // numPlanes samples.
3425 //
3426 addr = ComputeSurfaceAddrFromCoordMicroTiled(x,
3427 y,
3428 slice,
3429 sample,
3430 effectiveBpp,
3431 pitch,
3432 height,
3433 effectiveSamples,
3434 tileMode,
3435 ADDR_NON_DISPLAYABLE,
3436 TRUE,
3437 pBitPosition);
3438 }
3439
3440 return addr;
3441 }
3442
3443 /**
3444 ***************************************************************************************************
3445 * EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled
3446 *
3447 * @brief
3448 * Computes the FMASK address and bit position from a coordinate for 2D tilied (macro
3449 * tiled)
3450 * @return
3451 * The byte address
3452 ***************************************************************************************************
3453 */
3454 UINT_64 EgBasedAddrLib::ComputeFmaskAddrFromCoordMacroTiled(
3455 UINT_32 x, ///< [in] x coordinate
3456 UINT_32 y, ///< [in] y coordinate
3457 UINT_32 slice, ///< [in] slice index
3458 UINT_32 sample, ///< [in] sample number
3459 UINT_32 plane, ///< [in] plane number
3460 UINT_32 pitch, ///< [in] surface pitch in pixels
3461 UINT_32 height, ///< [in] surface height in pixels
3462 UINT_32 numSamples, ///< [in] number of samples
3463 AddrTileMode tileMode, ///< [in] tile mode
3464 UINT_32 pipeSwizzle, ///< [in] pipe swizzle
3465 UINT_32 bankSwizzle, ///< [in] bank swizzle
3466 BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine
3467 ADDR_TILEINFO* pTileInfo, ///< [in] bank structure.**All fields to be valid on entry**
3468 BOOL_32 resolved, ///< [in] TRUE if this is for resolved fmask
3469 UINT_32* pBitPosition ///< [out] pointer to returned bit position
3470 ) const
3471 {
3472 UINT_64 addr = 0;
3473 UINT_32 effectiveBpp;
3474 UINT_32 effectiveSamples;
3475
3476 //
3477 // 2xAA use the same layout as 4xAA
3478 //
3479 if (numSamples == 2)
3480 {
3481 numSamples = 4;
3482 }
3483
3484 //
3485 // Compute the number of planes.
3486 //
3487 if (!resolved)
3488 {
3489 effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3490 effectiveBpp = numSamples;
3491
3492 //
3493 // Compute the address just like a color surface with numSamples bits per element and
3494 // numPlanes samples.
3495 //
3496 addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
3497 y,
3498 slice,
3499 plane, // sample
3500 effectiveBpp,
3501 pitch,
3502 height,
3503 effectiveSamples,
3504 tileMode,
3505 ADDR_NON_DISPLAYABLE,// isdisp
3506 ignoreSE,// ignore_shader
3507 FALSE,// depth_sample_order
3508 pipeSwizzle,
3509 bankSwizzle,
3510 pTileInfo,
3511 pBitPosition);
3512
3513 //
3514 // Compute the real bit position. Each (sample, plane) is stored with one bit per sample.
3515 //
3516
3517
3518 //
3519 // Compute the pixel index with in the micro tile
3520 //
3521 UINT_32 pixelIndex = ComputePixelIndexWithinMicroTile(x ,
3522 y ,
3523 slice,
3524 effectiveBpp,
3525 tileMode,
3526 ADDR_NON_DISPLAYABLE);
3527
3528 *pBitPosition = ((pixelIndex * numSamples) + sample) & (BITS_PER_BYTE-1);
3529
3530 UINT_64 bitAddr = BYTES_TO_BITS(addr) + *pBitPosition;
3531
3532 addr = bitAddr / 8;
3533
3534 }
3535 else
3536 {
3537 effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3538 effectiveSamples = 1;
3539
3540 //
3541 // Compute the address just like a color surface with numSamples bits per element and
3542 // numPlanes samples.
3543 //
3544 addr = ComputeSurfaceAddrFromCoordMacroTiled(x,
3545 y,
3546 slice,
3547 sample,
3548 effectiveBpp,
3549 pitch,
3550 height,
3551 effectiveSamples,
3552 tileMode,
3553 ADDR_NON_DISPLAYABLE,
3554 ignoreSE,
3555 TRUE,
3556 pipeSwizzle,
3557 bankSwizzle,
3558 pTileInfo,
3559 pBitPosition);
3560 }
3561
3562 return addr;
3563 }
3564
3565 /**
3566 ***************************************************************************************************
3567 * EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled
3568 *
3569 * @brief
3570 * Compute (x,y,slice,sample,plane) coordinates from fmask address
3571 * @return
3572 * N/A
3573 *
3574 ***************************************************************************************************
3575 */
3576 VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMicroTiled(
3577 UINT_64 addr, ///< [in] byte address
3578 UINT_32 bitPosition,///< [in] bit position
3579 UINT_32 pitch, ///< [in] pitch in pixels
3580 UINT_32 height, ///< [in] height in pixels
3581 UINT_32 numSamples, ///< [in] number of samples (of color buffer)
3582 AddrTileMode tileMode, ///< [in] tile mode
3583 BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask
3584 UINT_32* pX, ///< [out] X coord
3585 UINT_32* pY, ///< [out] Y coord
3586 UINT_32* pSlice, ///< [out] slice index
3587 UINT_32* pSample, ///< [out] sample index
3588 UINT_32* pPlane ///< [out] plane index
3589 ) const
3590 {
3591 UINT_32 effectiveBpp;
3592 UINT_32 effectiveSamples;
3593
3594 // 2xAA use the same layout as 4xAA
3595 if (numSamples == 2)
3596 {
3597 numSamples = 4;
3598 }
3599
3600 if (!resolved)
3601 {
3602 effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3603 effectiveBpp = numSamples;
3604
3605 ComputeSurfaceCoordFromAddrMicroTiled(addr,
3606 bitPosition,
3607 effectiveBpp,
3608 pitch,
3609 height,
3610 effectiveSamples,
3611 tileMode,
3612 0, // tileBase
3613 0, // compBits
3614 pX,
3615 pY,
3616 pSlice,
3617 pPlane,
3618 ADDR_NON_DISPLAYABLE, // microTileType
3619 FALSE // isDepthSampleOrder
3620 );
3621
3622
3623 if ( pSample )
3624 {
3625 *pSample = bitPosition % numSamples;
3626 }
3627 }
3628 else
3629 {
3630 effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3631 effectiveSamples = 1;
3632
3633 ComputeSurfaceCoordFromAddrMicroTiled(addr,
3634 bitPosition,
3635 effectiveBpp,
3636 pitch,
3637 height,
3638 effectiveSamples,
3639 tileMode,
3640 0, // tileBase
3641 0, // compBits
3642 pX,
3643 pY,
3644 pSlice,
3645 pSample,
3646 ADDR_NON_DISPLAYABLE, // microTileType
3647 TRUE // isDepthSampleOrder
3648 );
3649 }
3650 }
3651
3652 /**
3653 ***************************************************************************************************
3654 * EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled
3655 *
3656 * @brief
3657 * Compute (x,y,slice,sample,plane) coordinates from
3658 * fmask address
3659 * @return
3660 * N/A
3661 *
3662 ***************************************************************************************************
3663 */
3664 VOID EgBasedAddrLib::ComputeFmaskCoordFromAddrMacroTiled(
3665 UINT_64 addr, ///< [in] byte address
3666 UINT_32 bitPosition,///< [in] bit position
3667 UINT_32 pitch, ///< [in] pitch in pixels
3668 UINT_32 height, ///< [in] height in pixels
3669 UINT_32 numSamples, ///< [in] number of samples (of color buffer)
3670 AddrTileMode tileMode, ///< [in] tile mode
3671 UINT_32 pipeSwizzle,///< [in] pipe swizzle
3672 UINT_32 bankSwizzle,///< [in] bank swizzle
3673 BOOL_32 ignoreSE, ///< [in] TRUE if ignore shader engine
3674 ADDR_TILEINFO* pTileInfo, ///< [in] bank structure. **All fields to be valid on entry**
3675 BOOL_32 resolved, ///< [in] TRUE if it is resolved fmask
3676 UINT_32* pX, ///< [out] X coord
3677 UINT_32* pY, ///< [out] Y coord
3678 UINT_32* pSlice, ///< [out] slice index
3679 UINT_32* pSample, ///< [out] sample index
3680 UINT_32* pPlane ///< [out] plane index
3681 ) const
3682 {
3683 UINT_32 effectiveBpp;
3684 UINT_32 effectiveSamples;
3685
3686 // 2xAA use the same layout as 4xAA
3687 if (numSamples == 2)
3688 {
3689 numSamples = 4;
3690 }
3691
3692 //
3693 // Compute the number of planes.
3694 //
3695 if (!resolved)
3696 {
3697 effectiveSamples = ComputeFmaskNumPlanesFromNumSamples(numSamples);
3698 effectiveBpp = numSamples;
3699
3700 ComputeSurfaceCoordFromAddrMacroTiled(addr,
3701 bitPosition,
3702 effectiveBpp,
3703 pitch,
3704 height,
3705 effectiveSamples,
3706 tileMode,
3707 0, // No tileBase
3708 0, // No compBits
3709 ADDR_NON_DISPLAYABLE,
3710 ignoreSE,
3711 FALSE,
3712 pipeSwizzle,
3713 bankSwizzle,
3714 pTileInfo,
3715 pX,
3716 pY,
3717 pSlice,
3718 pPlane);
3719
3720 if (pSample)
3721 {
3722 *pSample = bitPosition % numSamples;
3723 }
3724 }
3725 else
3726 {
3727 effectiveBpp = ComputeFmaskResolvedBppFromNumSamples(numSamples);
3728 effectiveSamples = 1;
3729
3730 ComputeSurfaceCoordFromAddrMacroTiled(addr,
3731 bitPosition,
3732 effectiveBpp,
3733 pitch,
3734 height,
3735 effectiveSamples,
3736 tileMode,
3737 0, // No tileBase
3738 0, // No compBits
3739 ADDR_NON_DISPLAYABLE,
3740 ignoreSE,
3741 TRUE,
3742 pipeSwizzle,
3743 bankSwizzle,
3744 pTileInfo,
3745 pX,
3746 pY,
3747 pSlice,
3748 pSample);
3749 }
3750 }
3751
3752 /**
3753 ***************************************************************************************************
3754 * EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr
3755 *
3756 * @brief
3757 * Compute (x,y,slice,sample,plane) coordinates from
3758 * fmask address
3759 * @return
3760 * N/A
3761 *
3762 ***************************************************************************************************
3763 */
3764 VOID EgBasedAddrLib::DispatchComputeFmaskCoordFromAddr(
3765 const ADDR_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
3766 ADDR_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
3767 ) const
3768 {
3769 UINT_64 addr = pIn->addr;
3770 UINT_32 bitPosition = pIn->bitPosition;
3771 UINT_32 pitch = pIn->pitch;
3772 UINT_32 height = pIn->height;
3773 UINT_32 numSamples = pIn->numSamples;
3774 AddrTileMode tileMode = pIn->tileMode;
3775 BOOL_32 ignoreSE = pIn->ignoreSE;
3776 ADDR_TILEINFO* pTileInfo = pIn->pTileInfo;
3777 BOOL_32 resolved = pIn->resolved;
3778
3779 UINT_32* pX = &pOut->x;
3780 UINT_32* pY = &pOut->y;
3781 UINT_32* pSlice = &pOut->slice;
3782 UINT_32* pSample = &pOut->sample;
3783 UINT_32* pPlane = &pOut->plane;
3784
3785 switch (tileMode)
3786 {
3787 case ADDR_TM_1D_TILED_THIN1:
3788 ComputeFmaskCoordFromAddrMicroTiled(addr,
3789 bitPosition,
3790 pitch,
3791 height,
3792 numSamples,
3793 tileMode,
3794 resolved,
3795 pX,
3796 pY,
3797 pSlice,
3798 pSample,
3799 pPlane);
3800 break;
3801 case ADDR_TM_2D_TILED_THIN1://fall through
3802 case ADDR_TM_3D_TILED_THIN1:
3803 UINT_32 pipeSwizzle;
3804 UINT_32 bankSwizzle;
3805
3806 if (m_configFlags.useCombinedSwizzle)
3807 {
3808 ExtractBankPipeSwizzle(pIn->tileSwizzle, pIn->pTileInfo,
3809 &bankSwizzle, &pipeSwizzle);
3810 }
3811 else
3812 {
3813 pipeSwizzle = pIn->pipeSwizzle;
3814 bankSwizzle = pIn->bankSwizzle;
3815 }
3816
3817 ComputeFmaskCoordFromAddrMacroTiled(addr,
3818 bitPosition,
3819 pitch,
3820 height,
3821 numSamples,
3822 tileMode,
3823 pipeSwizzle,
3824 bankSwizzle,
3825 ignoreSE,
3826 pTileInfo,
3827 resolved,
3828 pX,
3829 pY,
3830 pSlice,
3831 pSample,
3832 pPlane);
3833 break;
3834 default:
3835 ADDR_ASSERT_ALWAYS();
3836 break;
3837
3838 }
3839 }
3840 #endif
3841
3842 /**
3843 ***************************************************************************************************
3844 * EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples
3845 *
3846 * @brief
3847 * Compute fmask number of planes from number of samples
3848 *
3849 * @return
3850 * Number of planes
3851 ***************************************************************************************************
3852 */
3853 UINT_32 EgBasedAddrLib::ComputeFmaskNumPlanesFromNumSamples(
3854 UINT_32 numSamples) ///< [in] number of samples
3855 {
3856 UINT_32 numPlanes;
3857
3858 //
3859 // FMASK is stored such that each micro tile is composed of elements containing N bits, where
3860 // N is the number of samples. There is a micro tile for each bit in the FMASK address, and
3861 // micro tiles for each address bit, sometimes referred to as a plane, are stored sequentially.
3862 // The FMASK for a 2-sample surface looks like a general surface with 2 bits per element.
3863 // The FMASK for a 4-sample surface looks like a general surface with 4 bits per element and
3864 // 2 samples. The FMASK for an 8-sample surface looks like a general surface with 8 bits per
3865 // element and 4 samples. R6xx and R7xx only stored 3 planes for 8-sample FMASK surfaces.
3866 // This was changed for R8xx to simplify the logic in the CB.
3867 //
3868 switch (numSamples)
3869 {
3870 case 2:
3871 numPlanes = 1;
3872 break;
3873 case 4:
3874 numPlanes = 2;
3875 break;
3876 case 8:
3877 numPlanes = 4;
3878 break;
3879 default:
3880 ADDR_UNHANDLED_CASE();
3881 numPlanes = 0;
3882 break;
3883 }
3884 return numPlanes;
3885 }
3886
3887 /**
3888 ***************************************************************************************************
3889 * EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples
3890 *
3891 * @brief
3892 * Compute resolved fmask effective bpp based on number of samples
3893 *
3894 * @return
3895 * bpp
3896 ***************************************************************************************************
3897 */
3898 UINT_32 EgBasedAddrLib::ComputeFmaskResolvedBppFromNumSamples(
3899 UINT_32 numSamples) ///< number of samples
3900 {
3901 UINT_32 bpp;
3902
3903 //
3904 // Resolved FMASK surfaces are generated yBit the CB and read yBit the texture unit
3905 // so that the texture unit can read compressed multi-sample color data.
3906 // These surfaces store each index value packed per element.
3907 // Each element contains at least num_samples * log2(num_samples) bits.
3908 // Resolved FMASK surfaces are addressed as follows:
3909 // 2-sample Addressed similarly to a color surface with 8 bits per element and 1 sample.
3910 // 4-sample Addressed similarly to a color surface with 8 bits per element and 1 sample.
3911 // 8-sample Addressed similarly to a color surface with 32 bits per element and 1 sample.
3912
3913 switch (numSamples)
3914 {
3915 case 2:
3916 bpp = 8;
3917 break;
3918 case 4:
3919 bpp = 8;
3920 break;
3921 case 8:
3922 bpp = 32;
3923 break;
3924 default:
3925 ADDR_UNHANDLED_CASE();
3926 bpp = 0;
3927 break;
3928 }
3929 return bpp;
3930 }
3931
3932 /**
3933 ***************************************************************************************************
3934 * EgBasedAddrLib::IsTileInfoAllZero
3935 *
3936 * @brief
3937 * Return TRUE if all field are zero
3938 * @note
3939 * Since NULL input is consider to be all zero
3940 ***************************************************************************************************
3941 */
3942 BOOL_32 EgBasedAddrLib::IsTileInfoAllZero(
3943 ADDR_TILEINFO* pTileInfo)
3944 {
3945 BOOL_32 allZero = TRUE;
3946
3947 if (pTileInfo)
3948 {
3949 if ((pTileInfo->banks != 0) ||
3950 (pTileInfo->bankWidth != 0) ||
3951 (pTileInfo->bankHeight != 0) ||
3952 (pTileInfo->macroAspectRatio != 0) ||
3953 (pTileInfo->tileSplitBytes != 0) ||
3954 (pTileInfo->pipeConfig != 0)
3955 )
3956 {
3957 allZero = FALSE;
3958 }
3959 }
3960
3961 return allZero;
3962 }
3963
3964 /**
3965 ***************************************************************************************************
3966 * EgBasedAddrLib::HwlTileInfoEqual
3967 *
3968 * @brief
3969 * Return TRUE if all field are equal
3970 * @note
3971 * Only takes care of current HWL's data
3972 ***************************************************************************************************
3973 */
3974 BOOL_32 EgBasedAddrLib::HwlTileInfoEqual(
3975 const ADDR_TILEINFO* pLeft, ///<[in] Left compare operand
3976 const ADDR_TILEINFO* pRight ///<[in] Right compare operand
3977 ) const
3978 {
3979 BOOL_32 equal = FALSE;
3980
3981 if (pLeft->banks == pRight->banks &&
3982 pLeft->bankWidth == pRight->bankWidth &&
3983 pLeft->bankHeight == pRight->bankHeight &&
3984 pLeft->macroAspectRatio == pRight->macroAspectRatio &&
3985 pLeft->tileSplitBytes == pRight->tileSplitBytes)
3986 {
3987 equal = TRUE;
3988 }
3989
3990 return equal;
3991 }
3992
3993 /**
3994 ***************************************************************************************************
3995 * EgBasedAddrLib::HwlConvertTileInfoToHW
3996 * @brief
3997 * Entry of EgBasedAddrLib ConvertTileInfoToHW
3998 * @return
3999 * ADDR_E_RETURNCODE
4000 ***************************************************************************************************
4001 */
4002 ADDR_E_RETURNCODE EgBasedAddrLib::HwlConvertTileInfoToHW(
4003 const ADDR_CONVERT_TILEINFOTOHW_INPUT* pIn, ///< [in] input structure
4004 ADDR_CONVERT_TILEINFOTOHW_OUTPUT* pOut ///< [out] output structure
4005 ) const
4006 {
4007 ADDR_E_RETURNCODE retCode = ADDR_OK;
4008
4009 ADDR_TILEINFO *pTileInfoIn = pIn->pTileInfo;
4010 ADDR_TILEINFO *pTileInfoOut = pOut->pTileInfo;
4011
4012 if ((pTileInfoIn != NULL) && (pTileInfoOut != NULL))
4013 {
4014 if (pIn->reverse == FALSE)
4015 {
4016 switch (pTileInfoIn->banks)
4017 {
4018 case 2:
4019 pTileInfoOut->banks = 0;
4020 break;
4021 case 4:
4022 pTileInfoOut->banks = 1;
4023 break;
4024 case 8:
4025 pTileInfoOut->banks = 2;
4026 break;
4027 case 16:
4028 pTileInfoOut->banks = 3;
4029 break;
4030 default:
4031 ADDR_ASSERT_ALWAYS();
4032 retCode = ADDR_INVALIDPARAMS;
4033 pTileInfoOut->banks = 0;
4034 break;
4035 }
4036
4037 switch (pTileInfoIn->bankWidth)
4038 {
4039 case 1:
4040 pTileInfoOut->bankWidth = 0;
4041 break;
4042 case 2:
4043 pTileInfoOut->bankWidth = 1;
4044 break;
4045 case 4:
4046 pTileInfoOut->bankWidth = 2;
4047 break;
4048 case 8:
4049 pTileInfoOut->bankWidth = 3;
4050 break;
4051 default:
4052 ADDR_ASSERT_ALWAYS();
4053 retCode = ADDR_INVALIDPARAMS;
4054 pTileInfoOut->bankWidth = 0;
4055 break;
4056 }
4057
4058 switch (pTileInfoIn->bankHeight)
4059 {
4060 case 1:
4061 pTileInfoOut->bankHeight = 0;
4062 break;
4063 case 2:
4064 pTileInfoOut->bankHeight = 1;
4065 break;
4066 case 4:
4067 pTileInfoOut->bankHeight = 2;
4068 break;
4069 case 8:
4070 pTileInfoOut->bankHeight = 3;
4071 break;
4072 default:
4073 ADDR_ASSERT_ALWAYS();
4074 retCode = ADDR_INVALIDPARAMS;
4075 pTileInfoOut->bankHeight = 0;
4076 break;
4077 }
4078
4079 switch (pTileInfoIn->macroAspectRatio)
4080 {
4081 case 1:
4082 pTileInfoOut->macroAspectRatio = 0;
4083 break;
4084 case 2:
4085 pTileInfoOut->macroAspectRatio = 1;
4086 break;
4087 case 4:
4088 pTileInfoOut->macroAspectRatio = 2;
4089 break;
4090 case 8:
4091 pTileInfoOut->macroAspectRatio = 3;
4092 break;
4093 default:
4094 ADDR_ASSERT_ALWAYS();
4095 retCode = ADDR_INVALIDPARAMS;
4096 pTileInfoOut->macroAspectRatio = 0;
4097 break;
4098 }
4099
4100 switch (pTileInfoIn->tileSplitBytes)
4101 {
4102 case 64:
4103 pTileInfoOut->tileSplitBytes = 0;
4104 break;
4105 case 128:
4106 pTileInfoOut->tileSplitBytes = 1;
4107 break;
4108 case 256:
4109 pTileInfoOut->tileSplitBytes = 2;
4110 break;
4111 case 512:
4112 pTileInfoOut->tileSplitBytes = 3;
4113 break;
4114 case 1024:
4115 pTileInfoOut->tileSplitBytes = 4;
4116 break;
4117 case 2048:
4118 pTileInfoOut->tileSplitBytes = 5;
4119 break;
4120 case 4096:
4121 pTileInfoOut->tileSplitBytes = 6;
4122 break;
4123 default:
4124 ADDR_ASSERT_ALWAYS();
4125 retCode = ADDR_INVALIDPARAMS;
4126 pTileInfoOut->tileSplitBytes = 0;
4127 break;
4128 }
4129 }
4130 else
4131 {
4132 switch (pTileInfoIn->banks)
4133 {
4134 case 0:
4135 pTileInfoOut->banks = 2;
4136 break;
4137 case 1:
4138 pTileInfoOut->banks = 4;
4139 break;
4140 case 2:
4141 pTileInfoOut->banks = 8;
4142 break;
4143 case 3:
4144 pTileInfoOut->banks = 16;
4145 break;
4146 default:
4147 ADDR_ASSERT_ALWAYS();
4148 retCode = ADDR_INVALIDPARAMS;
4149 pTileInfoOut->banks = 2;
4150 break;
4151 }
4152
4153 switch (pTileInfoIn->bankWidth)
4154 {
4155 case 0:
4156 pTileInfoOut->bankWidth = 1;
4157 break;
4158 case 1:
4159 pTileInfoOut->bankWidth = 2;
4160 break;
4161 case 2:
4162 pTileInfoOut->bankWidth = 4;
4163 break;
4164 case 3:
4165 pTileInfoOut->bankWidth = 8;
4166 break;
4167 default:
4168 ADDR_ASSERT_ALWAYS();
4169 retCode = ADDR_INVALIDPARAMS;
4170 pTileInfoOut->bankWidth = 1;
4171 break;
4172 }
4173
4174 switch (pTileInfoIn->bankHeight)
4175 {
4176 case 0:
4177 pTileInfoOut->bankHeight = 1;
4178 break;
4179 case 1:
4180 pTileInfoOut->bankHeight = 2;
4181 break;
4182 case 2:
4183 pTileInfoOut->bankHeight = 4;
4184 break;
4185 case 3:
4186 pTileInfoOut->bankHeight = 8;
4187 break;
4188 default:
4189 ADDR_ASSERT_ALWAYS();
4190 retCode = ADDR_INVALIDPARAMS;
4191 pTileInfoOut->bankHeight = 1;
4192 break;
4193 }
4194
4195 switch (pTileInfoIn->macroAspectRatio)
4196 {
4197 case 0:
4198 pTileInfoOut->macroAspectRatio = 1;
4199 break;
4200 case 1:
4201 pTileInfoOut->macroAspectRatio = 2;
4202 break;
4203 case 2:
4204 pTileInfoOut->macroAspectRatio = 4;
4205 break;
4206 case 3:
4207 pTileInfoOut->macroAspectRatio = 8;
4208 break;
4209 default:
4210 ADDR_ASSERT_ALWAYS();
4211 retCode = ADDR_INVALIDPARAMS;
4212 pTileInfoOut->macroAspectRatio = 1;
4213 break;
4214 }
4215
4216 switch (pTileInfoIn->tileSplitBytes)
4217 {
4218 case 0:
4219 pTileInfoOut->tileSplitBytes = 64;
4220 break;
4221 case 1:
4222 pTileInfoOut->tileSplitBytes = 128;
4223 break;
4224 case 2:
4225 pTileInfoOut->tileSplitBytes = 256;
4226 break;
4227 case 3:
4228 pTileInfoOut->tileSplitBytes = 512;
4229 break;
4230 case 4:
4231 pTileInfoOut->tileSplitBytes = 1024;
4232 break;
4233 case 5:
4234 pTileInfoOut->tileSplitBytes = 2048;
4235 break;
4236 case 6:
4237 pTileInfoOut->tileSplitBytes = 4096;
4238 break;
4239 default:
4240 ADDR_ASSERT_ALWAYS();
4241 retCode = ADDR_INVALIDPARAMS;
4242 pTileInfoOut->tileSplitBytes = 64;
4243 break;
4244 }
4245 }
4246
4247 if (pTileInfoIn != pTileInfoOut)
4248 {
4249 pTileInfoOut->pipeConfig = pTileInfoIn->pipeConfig;
4250 }
4251 }
4252 else
4253 {
4254 ADDR_ASSERT_ALWAYS();
4255 retCode = ADDR_INVALIDPARAMS;
4256 }
4257
4258 return retCode;
4259 }
4260
4261 /**
4262 ***************************************************************************************************
4263 * EgBasedAddrLib::HwlComputeSurfaceInfo
4264 * @brief
4265 * Entry of EgBasedAddrLib ComputeSurfaceInfo
4266 * @return
4267 * ADDR_E_RETURNCODE
4268 ***************************************************************************************************
4269 */
4270 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceInfo(
4271 const ADDR_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
4272 ADDR_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
4273 ) const
4274 {
4275 ADDR_E_RETURNCODE retCode = ADDR_OK;
4276
4277 if (pIn->numSamples < pIn->numFrags)
4278 {
4279 retCode = ADDR_INVALIDPARAMS;
4280 }
4281
4282 ADDR_TILEINFO tileInfo = {0};
4283
4284 if (retCode == ADDR_OK)
4285 {
4286 // Uses internal tile info if pOut does not have a valid pTileInfo
4287 if (pOut->pTileInfo == NULL)
4288 {
4289 pOut->pTileInfo = &tileInfo;
4290 }
4291
4292 if (!DispatchComputeSurfaceInfo(pIn, pOut))
4293 {
4294 retCode = ADDR_INVALIDPARAMS;
4295 }
4296
4297 // Returns an index
4298 pOut->tileIndex = HwlPostCheckTileIndex(pOut->pTileInfo,
4299 pOut->tileMode,
4300 pOut->tileType,
4301 pOut->tileIndex);
4302
4303 if (IsMacroTiled(pOut->tileMode) && (pOut->macroModeIndex == TileIndexInvalid))
4304 {
4305 pOut->macroModeIndex = HwlComputeMacroModeIndex(pOut->tileIndex,
4306 pIn->flags,
4307 pIn->bpp,
4308 pIn->numSamples,
4309 pOut->pTileInfo);
4310 }
4311
4312 // Resets pTileInfo to NULL if the internal tile info is used
4313 if (pOut->pTileInfo == &tileInfo)
4314 {
4315 #if DEBUG
4316 // Client does not pass in a valid pTileInfo
4317 if (IsMacroTiled(pOut->tileMode))
4318 {
4319 // If a valid index is returned, then no pTileInfo is okay
4320 ADDR_ASSERT(!m_configFlags.useTileIndex || pOut->tileIndex != TileIndexInvalid);
4321
4322 if (!IsTileInfoAllZero(pIn->pTileInfo))
4323 {
4324 // The initial value of pIn->pTileInfo is copied to tileInfo
4325 // We do not expect any of these value to be changed nor any 0 of inputs
4326 ADDR_ASSERT(tileInfo.banks == pIn->pTileInfo->banks);
4327 ADDR_ASSERT(tileInfo.bankWidth == pIn->pTileInfo->bankWidth);
4328 ADDR_ASSERT(tileInfo.bankHeight == pIn->pTileInfo->bankHeight);
4329 ADDR_ASSERT(tileInfo.macroAspectRatio == pIn->pTileInfo->macroAspectRatio);
4330 ADDR_ASSERT(tileInfo.tileSplitBytes == pIn->pTileInfo->tileSplitBytes);
4331 }
4332 }
4333 #endif
4334 pOut->pTileInfo = NULL;
4335 }
4336 }
4337
4338 return retCode;
4339 }
4340
4341 /**
4342 ***************************************************************************************************
4343 * EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord
4344 * @brief
4345 * Entry of EgBasedAddrLib ComputeSurfaceAddrFromCoord
4346 * @return
4347 * ADDR_E_RETURNCODE
4348 ***************************************************************************************************
4349 */
4350 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceAddrFromCoord(
4351 const ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
4352 ADDR_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
4353 ) const
4354 {
4355 ADDR_E_RETURNCODE retCode = ADDR_OK;
4356
4357 if (
4358 #if !ALT_TEST // Overflow test needs this out-of-boundary coord
4359 (pIn->x > pIn->pitch) ||
4360 (pIn->y > pIn->height) ||
4361 #endif
4362 (pIn->numSamples > m_maxSamples))
4363 {
4364 retCode = ADDR_INVALIDPARAMS;
4365 }
4366 else
4367 {
4368 pOut->addr = DispatchComputeSurfaceAddrFromCoord(pIn, pOut);
4369 }
4370
4371 return retCode;
4372 }
4373
4374 /**
4375 ***************************************************************************************************
4376 * EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr
4377 * @brief
4378 * Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr
4379 * @return
4380 * ADDR_E_RETURNCODE
4381 ***************************************************************************************************
4382 */
4383 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSurfaceCoordFromAddr(
4384 const ADDR_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
4385 ADDR_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
4386 ) const
4387 {
4388 ADDR_E_RETURNCODE retCode = ADDR_OK;
4389
4390 if ((pIn->bitPosition >= 8) ||
4391 (pIn->numSamples > m_maxSamples))
4392 {
4393 retCode = ADDR_INVALIDPARAMS;
4394 }
4395 else
4396 {
4397 DispatchComputeSurfaceCoordFromAddr(pIn, pOut);
4398 }
4399 return retCode;
4400 }
4401
4402 /**
4403 ***************************************************************************************************
4404 * EgBasedAddrLib::HwlComputeSliceTileSwizzle
4405 * @brief
4406 * Entry of EgBasedAddrLib ComputeSurfaceCoordFromAddr
4407 * @return
4408 * ADDR_E_RETURNCODE
4409 ***************************************************************************************************
4410 */
4411 ADDR_E_RETURNCODE EgBasedAddrLib::HwlComputeSliceTileSwizzle(
4412 const ADDR_COMPUTE_SLICESWIZZLE_INPUT* pIn, ///< [in] input structure
4413 ADDR_COMPUTE_SLICESWIZZLE_OUTPUT* pOut ///< [out] output structure
4414 ) const
4415 {
4416 ADDR_E_RETURNCODE retCode = ADDR_OK;
4417
4418 if (pIn->pTileInfo && (pIn->pTileInfo->banks > 0))
4419 {
4420
4421 pOut->tileSwizzle = ComputeSliceTileSwizzle(pIn->tileMode,
4422 pIn->baseSwizzle,
4423 pIn->slice,
4424 pIn->baseAddr,
4425 pIn->pTileInfo);
4426 }
4427 else
4428 {
4429 retCode = ADDR_INVALIDPARAMS;
4430 }
4431
4432 return retCode;
4433 }
4434
4435 /**
4436 ***************************************************************************************************
4437 * EgBasedAddrLib::HwlComputeHtileBpp
4438 *
4439 * @brief
4440 * Compute htile bpp
4441 *
4442 * @return
4443 * Htile bpp
4444 ***************************************************************************************************
4445 */
4446 UINT_32 EgBasedAddrLib::HwlComputeHtileBpp(
4447 BOOL_32 isWidth8, ///< [in] TRUE if block width is 8
4448 BOOL_32 isHeight8 ///< [in] TRUE if block height is 8
4449 ) const
4450 {
4451 // only support 8x8 mode
4452 ADDR_ASSERT(isWidth8 && isHeight8);
4453 return 32;
4454 }
4455
4456 /**
4457 ***************************************************************************************************
4458 * EgBasedAddrLib::HwlComputeHtileBaseAlign
4459 *
4460 * @brief
4461 * Compute htile base alignment
4462 *
4463 * @return
4464 * Htile base alignment
4465 ***************************************************************************************************
4466 */
4467 UINT_32 EgBasedAddrLib::HwlComputeHtileBaseAlign(
4468 BOOL_32 isTcCompatible, ///< [in] if TC compatible
4469 BOOL_32 isLinear, ///< [in] if it is linear mode
4470 ADDR_TILEINFO* pTileInfo ///< [in] Tile info
4471 ) const
4472 {
4473 UINT_32 baseAlign = m_pipeInterleaveBytes * HwlGetPipes(pTileInfo);
4474
4475 if (isTcCompatible)
4476 {
4477 ADDR_ASSERT(pTileInfo != NULL);
4478 if (pTileInfo)
4479 {
4480 baseAlign *= pTileInfo->banks;
4481 }
4482 }
4483
4484 return baseAlign;
4485 }
4486
4487 /**
4488 ***************************************************************************************************
4489 * EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled
4490 *
4491 * @brief
4492 * Compute 1D tiled surface pitch alignment, calculation results are returned through
4493 * output parameters.
4494 *
4495 * @return
4496 * pitch alignment
4497 ***************************************************************************************************
4498 */
4499 UINT_32 EgBasedAddrLib::HwlGetPitchAlignmentMicroTiled(
4500 AddrTileMode tileMode, ///< [in] tile mode
4501 UINT_32 bpp, ///< [in] bits per pixel
4502 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
4503 UINT_32 numSamples ///< [in] number of samples
4504 ) const
4505 {
4506 UINT_32 pitchAlign;
4507
4508 UINT_32 microTileThickness = ComputeSurfaceThickness(tileMode);
4509
4510 UINT_32 pixelsPerMicroTile;
4511 UINT_32 pixelsPerPipeInterleave;
4512 UINT_32 microTilesPerPipeInterleave;
4513
4514 //
4515 // Special workaround for depth/stencil buffer, use 8 bpp to meet larger requirement for
4516 // stencil buffer since pitch alignment is related to bpp.
4517 // For a depth only buffer do not set this.
4518 //
4519 // Note: this actually does not work for mipmap but mipmap depth texture is not really
4520 // sampled with mipmap.
4521 //
4522 if (flags.depth && !flags.noStencil)
4523 {
4524 bpp = 8;
4525 }
4526
4527 pixelsPerMicroTile = MicroTilePixels * microTileThickness;
4528 pixelsPerPipeInterleave = BYTES_TO_BITS(m_pipeInterleaveBytes) / (bpp * numSamples);
4529 microTilesPerPipeInterleave = pixelsPerPipeInterleave / pixelsPerMicroTile;
4530
4531 pitchAlign = Max(MicroTileWidth, microTilesPerPipeInterleave * MicroTileWidth);
4532
4533 return pitchAlign;
4534 }
4535
4536 /**
4537 ***************************************************************************************************
4538 * EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled
4539 *
4540 * @brief
4541 * Adjust 1D tiled surface pitch and slice size
4542 *
4543 * @return
4544 * Logical slice size in bytes
4545 ***************************************************************************************************
4546 */
4547 UINT_64 EgBasedAddrLib::HwlGetSizeAdjustmentMicroTiled(
4548 UINT_32 thickness, ///< [in] thickness
4549 UINT_32 bpp, ///< [in] bits per pixel
4550 ADDR_SURFACE_FLAGS flags, ///< [in] surface flags
4551 UINT_32 numSamples, ///< [in] number of samples
4552 UINT_32 baseAlign, ///< [in] base alignment
4553 UINT_32 pitchAlign, ///< [in] pitch alignment
4554 UINT_32* pPitch, ///< [in/out] pointer to pitch
4555 UINT_32* pHeight ///< [in/out] pointer to height
4556 ) const
4557 {
4558 UINT_64 logicalSliceSize;
4559 UINT_64 physicalSliceSize;
4560
4561 UINT_32 pitch = *pPitch;
4562 UINT_32 height = *pHeight;
4563
4564 // Logical slice: pitch * height * bpp * numSamples (no 1D MSAA so actually numSamples == 1)
4565 logicalSliceSize = BITS_TO_BYTES(static_cast<UINT_64>(pitch) * height * bpp * numSamples);
4566
4567 // Physical slice: multiplied by thickness
4568 physicalSliceSize = logicalSliceSize * thickness;
4569
4570 //
4571 // R800 will always pad physical slice size to baseAlign which is pipe_interleave_bytes
4572 //
4573 ADDR_ASSERT((physicalSliceSize % baseAlign) == 0)
4574
4575 return logicalSliceSize;
4576 }
4577