amd/addrlib: import gfx9 support
[mesa.git] / src / amd / addrlib / core / addrlib2.cpp
1 /*
2 * Copyright © 2017 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 addrlib2.cpp
30 * @brief Contains the implementation for the AddrLib2 base class.
31 ****************************************************************************************************
32 */
33
34 #include "addrinterface.h"
35 #include "addrlib2.h"
36 #include "addrcommon.h"
37
38 namespace Addr
39 {
40 namespace V2
41 {
42
43 ////////////////////////////////////////////////////////////////////////////////////////////////////
44 // Static Const Member
45 ////////////////////////////////////////////////////////////////////////////////////////////////////
46
47 const SwizzleModeFlags Lib::SwizzleModeTable[ADDR_SW_MAX_TYPE] =
48 {//Linear 256B 4KB 64KB Var Z Std Disp Rot XOR T
49 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//ADDR_SW_LINEAR
50 {0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0},//ADDR_SW_256B_S
51 {0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0},//ADDR_SW_256B_D
52 {0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0},//ADDR_SW_256B_R
53
54 {0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0},//ADDR_SW_4KB_Z
55 {0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0},//ADDR_SW_4KB_S
56 {0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0},//ADDR_SW_4KB_D
57 {0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},//ADDR_SW_4KB_R
58
59 {0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0},//ADDR_SW_64KB_Z
60 {0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0},//ADDR_SW_64KB_S
61 {0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0},//ADDR_SW_64KB_D
62 {0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0},//ADDR_SW_64KB_R
63
64 {0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0},//ADDR_SW_VAR_Z
65 {0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0},//ADDR_SW_VAR_S
66 {0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},//ADDR_SW_VAR_D
67 {0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0},//ADDR_SW_VAR_R
68
69 {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1},//ADDR_SW_64KB_Z_T
70 {0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1},//ADDR_SW_64KB_S_T
71 {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 1},//ADDR_SW_64KB_D_T
72 {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1},//ADDR_SW_64KB_R_T
73
74 {0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0},//ADDR_SW_4KB_Z_x
75 {0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0},//ADDR_SW_4KB_S_x
76 {0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0},//ADDR_SW_4KB_D_x
77 {0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0},//ADDR_SW_4KB_R_x
78
79 {0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0},//ADDR_SW_64KB_Z_X
80 {0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0},//ADDR_SW_64KB_S_X
81 {0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0},//ADDR_SW_64KB_D_X
82 {0, 0, 0, 1, 0, 0, 0, 0, 1, 1, 0},//ADDR_SW_64KB_R_X
83
84 {0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0},//ADDR_SW_VAR_Z_X
85 {0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0},//ADDR_SW_VAR_S_X
86 {0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0},//ADDR_SW_VAR_D_X
87 {0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0},//ADDR_SW_VAR_R_X
88 {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},//ADDR_SW_LINEAR_GENERAL
89 };
90
91 const Dim2d Lib::Block256b[] = {{16, 16}, {16, 8}, {8, 8}, {8, 4}, {4, 4}};
92
93 const Dim3d Lib::Block1kb[] = {{16, 8, 8}, {8, 8, 8}, {8, 8, 4}, {8, 4, 4}, {4, 4, 4}};
94
95 const Dim2d Lib::CompressBlock2d[] = {{16, 16}, {16, 8}, {8, 8}, {8, 4}, {4, 4}};
96
97 const Dim3d Lib::CompressBlock3dS[] = {{16, 4, 4}, {8, 4, 4}, {4, 4, 4}, {2, 4, 4}, {1, 4, 4}};
98
99 const Dim3d Lib::CompressBlock3dZ[] = {{8, 4, 8}, {4, 4, 8}, {4, 4, 4}, {4, 2, 4}, {2, 2, 4}};
100
101 const UINT_32 Lib::MaxMacroBits = 20;
102
103 const UINT_32 Lib::MipTailOffset[] = {2048, 1024, 512, 256, 128, 64, 32, 16,
104 8, 6, 5, 4, 3, 2, 1, 0};
105
106 ////////////////////////////////////////////////////////////////////////////////////////////////////
107 // Constructor/Destructor
108 ////////////////////////////////////////////////////////////////////////////////////////////////////
109
110 /**
111 ****************************************************************************************************
112 * Lib::Lib
113 *
114 * @brief
115 * Constructor for the Addr::V2::Lib class
116 *
117 ****************************************************************************************************
118 */
119 Lib::Lib()
120 :
121 Addr::Lib()
122 {
123 }
124
125 /**
126 ****************************************************************************************************
127 * Lib::Lib
128 *
129 * @brief
130 * Constructor for the AddrLib2 class with hClient as parameter
131 *
132 ****************************************************************************************************
133 */
134 Lib::Lib(const Client* pClient)
135 :
136 Addr::Lib(pClient)
137 {
138 }
139
140 /**
141 ****************************************************************************************************
142 * Lib::~Lib
143 *
144 * @brief
145 * Destructor for the AddrLib2 class
146 *
147 ****************************************************************************************************
148 */
149 Lib::~Lib()
150 {
151 }
152
153 /**
154 ****************************************************************************************************
155 * Lib::GetLib
156 *
157 * @brief
158 * Get Addr::V2::Lib pointer
159 *
160 * @return
161 * An Addr::V2::Lib class pointer
162 ****************************************************************************************************
163 */
164 Lib* Lib::GetLib(
165 ADDR_HANDLE hLib) ///< [in] handle of ADDR_HANDLE
166 {
167 Addr::Lib* pAddrLib = Addr::Lib::GetLib(hLib);
168 if ((pAddrLib != NULL) &&
169 (pAddrLib->GetChipFamily() <= ADDR_CHIP_FAMILY_VI))
170 {
171 // only valid and GFX9+ AISC can use AddrLib2 function.
172 ADDR_ASSERT_ALWAYS();
173 hLib = NULL;
174 }
175 return static_cast<Lib*>(hLib);
176 }
177
178
179 ////////////////////////////////////////////////////////////////////////////////////////////////////
180 // Surface Methods
181 ////////////////////////////////////////////////////////////////////////////////////////////////////
182
183
184 /**
185 ****************************************************************************************************
186 * Lib::ComputeSurfaceInfo
187 *
188 * @brief
189 * Interface function stub of AddrComputeSurfaceInfo.
190 *
191 * @return
192 * ADDR_E_RETURNCODE
193 ****************************************************************************************************
194 */
195 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfo(
196 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
197 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
198 ) const
199 {
200 ADDR_E_RETURNCODE returnCode = ADDR_OK;
201
202 if (GetFillSizeFieldsFlags() == TRUE)
203 {
204 if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT)) ||
205 (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT)))
206 {
207 returnCode = ADDR_PARAMSIZEMISMATCH;
208 }
209 }
210
211 // Adjust coming parameters.
212 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = *pIn;
213 localIn.width = Max(pIn->width, 1u);
214 localIn.height = Max(pIn->height, 1u);
215 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
216 localIn.numSlices = Max(pIn->numSlices, 1u);
217 localIn.numSamples = Max(pIn->numSamples, 1u);
218 localIn.numFrags = (localIn.numFrags == 0) ? localIn.numSamples : pIn->numFrags;
219
220 UINT_32 expandX = 1;
221 UINT_32 expandY = 1;
222 ElemMode elemMode = ADDR_UNCOMPRESSED;
223
224 if (returnCode == ADDR_OK)
225 {
226 // Set format to INVALID will skip this conversion
227 if (localIn.format != ADDR_FMT_INVALID)
228 {
229 // Get compression/expansion factors and element mode which indicates compression/expansion
230 localIn.bpp = GetElemLib()->GetBitsPerPixel(localIn.format,
231 &elemMode,
232 &expandX,
233 &expandY);
234
235 // Special flag for 96 bit surface. 96 (or 48 if we support) bit surface's width is
236 // pre-multiplied by 3 and bpp is divided by 3. So pitch alignment for linear-
237 // aligned does not meet 64-pixel in real. We keep special handling in hwl since hw
238 // restrictions are different.
239 // Also Mip 1+ needs an element pitch of 32 bits so we do not need this workaround
240 // but we use this flag to skip RestoreSurfaceInfo below
241
242 if ((elemMode == ADDR_EXPANDED) && (expandX > 1))
243 {
244 ADDR_ASSERT((localIn.swizzleMode == ADDR_SW_LINEAR) || (localIn.height == 1));
245 }
246
247 UINT_32 basePitch = 0;
248 GetElemLib()->AdjustSurfaceInfo(elemMode,
249 expandX,
250 expandY,
251 &localIn.bpp,
252 &basePitch,
253 &localIn.width,
254 &localIn.height);
255
256 // Overwrite these parameters if we have a valid format
257 }
258
259 if (localIn.bpp != 0)
260 {
261 localIn.width = Max(localIn.width, 1u);
262 localIn.height = Max(localIn.height, 1u);
263 }
264 else // Rule out some invalid parameters
265 {
266 ADDR_ASSERT_ALWAYS();
267
268 returnCode = ADDR_INVALIDPARAMS;
269 }
270 }
271
272 if (returnCode == ADDR_OK)
273 {
274 returnCode = ComputeSurfaceInfoSanityCheck(&localIn);
275 }
276
277 if (returnCode == ADDR_OK)
278 {
279 VerifyMipLevelInfo(pIn);
280
281 if (IsLinear(pIn->swizzleMode))
282 {
283 // linear mode
284 returnCode = ComputeSurfaceInfoLinear(&localIn, pOut);
285 }
286 else
287 {
288 // tiled mode
289 returnCode = ComputeSurfaceInfoTiled(&localIn, pOut);
290 }
291
292 if (returnCode == ADDR_OK)
293 {
294 pOut->bpp = localIn.bpp;
295 pOut->pixelPitch = pOut->pitch;
296 pOut->pixelHeight = pOut->height;
297 pOut->pixelMipChainPitch = pOut->mipChainPitch;
298 pOut->pixelMipChainHeight = pOut->mipChainHeight;
299 pOut->pixelBits = localIn.bpp;
300
301 if (localIn.format != ADDR_FMT_INVALID)
302 {
303 UINT_32 pixelBits = pOut->pixelBits;
304
305 GetElemLib()->RestoreSurfaceInfo(elemMode,
306 expandX,
307 expandY,
308 &pOut->pixelBits,
309 &pOut->pixelPitch,
310 &pOut->pixelHeight);
311
312 GetElemLib()->RestoreSurfaceInfo(elemMode,
313 expandX,
314 expandY,
315 &pixelBits,
316 &pOut->pixelMipChainPitch,
317 &pOut->pixelMipChainHeight);
318 }
319
320 if (localIn.flags.needEquation && (Log2(localIn.numFrags) == 0))
321 {
322 pOut->equationIndex = GetEquationIndex(&localIn, pOut);
323 }
324 }
325 }
326
327 return returnCode;
328 }
329
330 /**
331 ****************************************************************************************************
332 * Lib::ComputeSurfaceInfo
333 *
334 * @brief
335 * Interface function stub of AddrComputeSurfaceInfo.
336 *
337 * @return
338 * ADDR_E_RETURNCODE
339 ****************************************************************************************************
340 */
341 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoord(
342 const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
343 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
344 ) const
345 {
346 ADDR_E_RETURNCODE returnCode = ADDR_OK;
347
348 if (GetFillSizeFieldsFlags() == TRUE)
349 {
350 if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT)) ||
351 (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT)))
352 {
353 returnCode = ADDR_PARAMSIZEMISMATCH;
354 }
355 }
356
357 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT localIn = *pIn;
358 localIn.unalignedWidth = Max(pIn->unalignedWidth, 1u);
359 localIn.unalignedHeight = Max(pIn->unalignedHeight, 1u);
360 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
361 localIn.numSlices = Max(pIn->numSlices, 1u);
362 localIn.numSamples = Max(pIn->numSamples, 1u);
363 localIn.numFrags = Max(pIn->numFrags, 1u);
364
365 if ((localIn.bpp < 8) ||
366 (localIn.bpp > 128) ||
367 ((localIn.bpp % 8) != 0) ||
368 (localIn.sample >= localIn.numSamples) ||
369 (localIn.slice >= localIn.numSlices) ||
370 (localIn.mipId >= localIn.numMipLevels) ||
371 (IsTex3d(localIn.resourceType) &&
372 (Valid3DMipSliceIdConstraint(localIn.numSlices, localIn.mipId, localIn.slice) == FALSE)))
373 {
374 returnCode = ADDR_INVALIDPARAMS;
375 }
376
377 if (returnCode == ADDR_OK)
378 {
379 if (IsLinear(localIn.swizzleMode))
380 {
381 returnCode = ComputeSurfaceAddrFromCoordLinear(&localIn, pOut);
382 }
383 else
384 {
385 returnCode = ComputeSurfaceAddrFromCoordTiled(&localIn, pOut);
386 }
387 }
388
389 return returnCode;
390 }
391
392 /**
393 ****************************************************************************************************
394 * Lib::ComputeSurfaceCoordFromAddr
395 *
396 * @brief
397 * Interface function stub of ComputeSurfaceCoordFromAddr.
398 *
399 * @return
400 * ADDR_E_RETURNCODE
401 ****************************************************************************************************
402 */
403 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddr(
404 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
405 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
406 ) const
407 {
408 ADDR_E_RETURNCODE returnCode = ADDR_OK;
409
410 if (GetFillSizeFieldsFlags() == TRUE)
411 {
412 if ((pIn->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT)) ||
413 (pOut->size != sizeof(ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT)))
414 {
415 returnCode = ADDR_PARAMSIZEMISMATCH;
416 }
417 }
418
419 if ((pIn->bpp < 8) ||
420 (pIn->bpp > 128) ||
421 ((pIn->bpp % 8) != 0) ||
422 (pIn->bitPosition >= 8))
423 {
424 returnCode = ADDR_INVALIDPARAMS;
425 }
426
427 if (returnCode == ADDR_OK)
428 {
429 if (IsLinear(pIn->swizzleMode))
430 {
431 returnCode = ComputeSurfaceCoordFromAddrLinear(pIn, pOut);
432 }
433 else
434 {
435 returnCode = ComputeSurfaceCoordFromAddrTiled(pIn, pOut);
436 }
437 }
438
439 return returnCode;
440 }
441
442
443 ////////////////////////////////////////////////////////////////////////////////////////////////////
444 // CMASK/HTILE
445 ////////////////////////////////////////////////////////////////////////////////////////////////////
446
447 /**
448 ****************************************************************************************************
449 * Lib::ComputeHtileInfo
450 *
451 * @brief
452 * Interface function stub of AddrComputeHtilenfo
453 *
454 * @return
455 * ADDR_E_RETURNCODE
456 ****************************************************************************************************
457 */
458 ADDR_E_RETURNCODE Lib::ComputeHtileInfo(
459 const ADDR2_COMPUTE_HTILE_INFO_INPUT* pIn, ///< [in] input structure
460 ADDR2_COMPUTE_HTILE_INFO_OUTPUT* pOut ///< [out] output structure
461 ) const
462 {
463 ADDR_E_RETURNCODE returnCode;
464
465 if ((GetFillSizeFieldsFlags() == TRUE) &&
466 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_INPUT)) ||
467 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_INFO_OUTPUT))))
468 {
469 returnCode = ADDR_INVALIDPARAMS;
470 }
471 else
472 {
473 returnCode = HwlComputeHtileInfo(pIn, pOut);
474 }
475
476 return returnCode;
477 }
478
479 /**
480 ****************************************************************************************************
481 * Lib::ComputeHtileAddrFromCoord
482 *
483 * @brief
484 * Interface function stub of AddrComputeHtileAddrFromCoord
485 *
486 * @return
487 * ADDR_E_RETURNCODE
488 ****************************************************************************************************
489 */
490 ADDR_E_RETURNCODE Lib::ComputeHtileAddrFromCoord(
491 const ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
492 ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
493 ) const
494 {
495 ADDR_E_RETURNCODE returnCode;
496
497 if ((GetFillSizeFieldsFlags() == TRUE) &&
498 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_INPUT)) ||
499 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_ADDRFROMCOORD_OUTPUT))))
500 {
501 returnCode = ADDR_INVALIDPARAMS;
502 }
503 else
504 {
505 returnCode = HwlComputeHtileAddrFromCoord(pIn, pOut);
506 }
507
508 return returnCode;
509 }
510
511 /**
512 ****************************************************************************************************
513 * Lib::ComputeHtileCoordFromAddr
514 *
515 * @brief
516 * Interface function stub of AddrComputeHtileCoordFromAddr
517 *
518 * @return
519 * ADDR_E_RETURNCODE
520 ****************************************************************************************************
521 */
522 ADDR_E_RETURNCODE Lib::ComputeHtileCoordFromAddr(
523 const ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
524 ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
525 ) const
526 {
527 ADDR_E_RETURNCODE returnCode;
528
529 if ((GetFillSizeFieldsFlags() == TRUE) &&
530 ((pIn->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_INPUT)) ||
531 (pOut->size != sizeof(ADDR2_COMPUTE_HTILE_COORDFROMADDR_OUTPUT))))
532 {
533 returnCode = ADDR_INVALIDPARAMS;
534 }
535 else
536 {
537 returnCode = HwlComputeHtileCoordFromAddr(pIn, pOut);
538 }
539
540 return returnCode;
541 }
542
543 /**
544 ****************************************************************************************************
545 * Lib::ComputeCmaskInfo
546 *
547 * @brief
548 * Interface function stub of AddrComputeCmaskInfo
549 *
550 * @return
551 * ADDR_E_RETURNCODE
552 ****************************************************************************************************
553 */
554 ADDR_E_RETURNCODE Lib::ComputeCmaskInfo(
555 const ADDR2_COMPUTE_CMASK_INFO_INPUT* pIn, ///< [in] input structure
556 ADDR2_COMPUTE_CMASK_INFO_OUTPUT* pOut ///< [out] output structure
557 ) const
558 {
559 ADDR_E_RETURNCODE returnCode;
560
561 if ((GetFillSizeFieldsFlags() == TRUE) &&
562 ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_INPUT)) ||
563 (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_INFO_OUTPUT))))
564 {
565 returnCode = ADDR_INVALIDPARAMS;
566 }
567 else if (pIn->cMaskFlags.linear)
568 {
569 returnCode = ADDR_INVALIDPARAMS;
570 }
571 else
572 {
573 returnCode = HwlComputeCmaskInfo(pIn, pOut);
574 }
575
576 return returnCode;
577 }
578
579 /**
580 ****************************************************************************************************
581 * Lib::ComputeCmaskAddrFromCoord
582 *
583 * @brief
584 * Interface function stub of AddrComputeCmaskAddrFromCoord
585 *
586 * @return
587 * ADDR_E_RETURNCODE
588 ****************************************************************************************************
589 */
590 ADDR_E_RETURNCODE Lib::ComputeCmaskAddrFromCoord(
591 const ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
592 ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
593 ) const
594 {
595 ADDR_E_RETURNCODE returnCode;
596
597 if ((GetFillSizeFieldsFlags() == TRUE) &&
598 ((pIn->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_INPUT)) ||
599 (pOut->size != sizeof(ADDR2_COMPUTE_CMASK_ADDRFROMCOORD_OUTPUT))))
600 {
601 returnCode = ADDR_INVALIDPARAMS;
602 }
603 else
604 {
605 returnCode = HwlComputeCmaskAddrFromCoord(pIn, pOut);
606 }
607
608 return returnCode;
609 }
610
611 /**
612 ****************************************************************************************************
613 * Lib::ComputeCmaskCoordFromAddr
614 *
615 * @brief
616 * Interface function stub of AddrComputeCmaskCoordFromAddr
617 *
618 * @return
619 * ADDR_E_RETURNCODE
620 ****************************************************************************************************
621 */
622 ADDR_E_RETURNCODE Lib::ComputeCmaskCoordFromAddr(
623 const ADDR2_COMPUTE_CMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
624 ADDR2_COMPUTE_CMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
625 ) const
626 {
627 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
628
629 ADDR_NOT_IMPLEMENTED();
630
631 return returnCode;
632 }
633
634 /**
635 ****************************************************************************************************
636 * Lib::ComputeFmaskInfo
637 *
638 * @brief
639 * Interface function stub of ComputeFmaskInfo.
640 *
641 * @return
642 * ADDR_E_RETURNCODE
643 ****************************************************************************************************
644 */
645 ADDR_E_RETURNCODE Lib::ComputeFmaskInfo(
646 const ADDR2_COMPUTE_FMASK_INFO_INPUT* pIn, ///< [in] input structure
647 ADDR2_COMPUTE_FMASK_INFO_OUTPUT* pOut ///< [out] output structure
648 )
649 {
650 ADDR_E_RETURNCODE returnCode;
651
652 BOOL_32 valid = (IsZOrderSwizzle(pIn->swizzleMode) == TRUE) &&
653 ((pIn->numSamples > 0) || (pIn->numFrags > 0));
654
655 if (GetFillSizeFieldsFlags())
656 {
657 if ((pIn->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_INPUT)) ||
658 (pOut->size != sizeof(ADDR2_COMPUTE_FMASK_INFO_OUTPUT)))
659 {
660 valid = FALSE;
661 }
662 }
663
664 if (valid == FALSE)
665 {
666 returnCode = ADDR_INVALIDPARAMS;
667 }
668 else
669 {
670 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
671 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
672
673 localIn.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_INPUT);
674 localOut.size = sizeof(ADDR2_COMPUTE_SURFACE_INFO_OUTPUT);
675
676 localIn.swizzleMode = pIn->swizzleMode;
677 localIn.numSlices = Max(pIn->numSlices, 1u);
678 localIn.width = Max(pIn->unalignedWidth, 1u);
679 localIn.height = Max(pIn->unalignedHeight, 1u);
680 localIn.bpp = GetFmaskBpp(pIn->numSamples, pIn->numFrags);
681 localIn.flags.fmask = 1;
682 localIn.numFrags = 1;
683 localIn.numSamples = 1;
684 localIn.resourceType = ADDR_RSRC_TEX_2D;
685
686 if (localIn.bpp == 8)
687 {
688 localIn.format = ADDR_FMT_8;
689 }
690 else if (localIn.bpp == 16)
691 {
692 localIn.format = ADDR_FMT_16;
693 }
694 else if (localIn.bpp == 32)
695 {
696 localIn.format = ADDR_FMT_32;
697 }
698 else
699 {
700 localIn.format = ADDR_FMT_32_32;
701 }
702
703 returnCode = ComputeSurfaceInfo(&localIn, &localOut);
704
705 if (returnCode == ADDR_OK)
706 {
707 pOut->pitch = localOut.pitch;
708 pOut->height = localOut.height;
709 pOut->baseAlign = localOut.baseAlign;
710 pOut->numSlices = localOut.numSlices;
711 pOut->fmaskBytes = static_cast<UINT_32>(localOut.surfSize);
712 pOut->sliceSize = localOut.sliceSize;
713 pOut->bpp = localIn.bpp;
714 pOut->numSamples = 1;
715 }
716 }
717
718 return returnCode;
719 }
720
721 /**
722 ****************************************************************************************************
723 * Lib::ComputeFmaskAddrFromCoord
724 *
725 * @brief
726 * Interface function stub of ComputeFmaskAddrFromCoord.
727 *
728 * @return
729 * ADDR_E_RETURNCODE
730 ****************************************************************************************************
731 */
732 ADDR_E_RETURNCODE Lib::ComputeFmaskAddrFromCoord(
733 const ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
734 ADDR2_COMPUTE_FMASK_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
735 ) const
736 {
737 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
738
739 ADDR_NOT_IMPLEMENTED();
740
741 return returnCode;
742 }
743
744 /**
745 ****************************************************************************************************
746 * Lib::ComputeFmaskCoordFromAddr
747 *
748 * @brief
749 * Interface function stub of ComputeFmaskAddrFromCoord.
750 *
751 * @return
752 * ADDR_E_RETURNCODE
753 ****************************************************************************************************
754 */
755 ADDR_E_RETURNCODE Lib::ComputeFmaskCoordFromAddr(
756 const ADDR2_COMPUTE_FMASK_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
757 ADDR2_COMPUTE_FMASK_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
758 ) const
759 {
760 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
761
762 ADDR_NOT_IMPLEMENTED();
763
764 return returnCode;
765 }
766
767 /**
768 ****************************************************************************************************
769 * Lib::GetMetaMiptailInfo
770 *
771 * @brief
772 * Get mip tail coordinate information.
773 *
774 * @return
775 * N/A
776 ****************************************************************************************************
777 */
778 VOID Lib::GetMetaMiptailInfo(
779 ADDR2_META_MIP_INFO* pInfo, ///< [out] output structure to store per mip coord
780 Dim3d mipCoord, ///< [in] mip tail base coord
781 UINT_32 numMipInTail, ///< [in] number of mips in tail
782 Dim3d* pMetaBlkDim ///< [in] meta block width/height/depth
783 ) const
784 {
785 BOOL_32 isThick = (pMetaBlkDim->d > 1);
786 UINT_32 mipWidth = pMetaBlkDim->w;
787 UINT_32 mipHeight = pMetaBlkDim->h >> 1;
788 UINT_32 mipDepth = pMetaBlkDim->d;
789 UINT_32 minInc;
790
791 if (isThick)
792 {
793 minInc = (pMetaBlkDim->h >= 512) ? 128 : ((pMetaBlkDim->h == 256) ? 64 : 32);
794 }
795 else if (pMetaBlkDim->h >= 1024)
796 {
797 minInc = 256;
798 }
799 else if (pMetaBlkDim->h == 512)
800 {
801 minInc = 128;
802 }
803 else
804 {
805 minInc = 64;
806 }
807
808 UINT_32 blk32MipId = 0xFFFFFFFF;
809
810 for (UINT_32 mip = 0; mip < numMipInTail; mip++)
811 {
812 pInfo[mip].inMiptail = TRUE;
813 pInfo[mip].startX = mipCoord.w;
814 pInfo[mip].startY = mipCoord.h;
815 pInfo[mip].startZ = mipCoord.d;
816 pInfo[mip].width = mipWidth;
817 pInfo[mip].height = mipHeight;
818 pInfo[mip].depth = mipDepth;
819
820 if (mipWidth <= 32)
821 {
822 if (blk32MipId == 0xFFFFFFFF)
823 {
824 blk32MipId = mip;
825 }
826
827 mipCoord.w = pInfo[blk32MipId].startX;
828 mipCoord.h = pInfo[blk32MipId].startY;
829 mipCoord.d = pInfo[blk32MipId].startZ;
830
831 switch (mip - blk32MipId)
832 {
833 case 0:
834 mipCoord.w += 32; // 16x16
835 break;
836 case 1:
837 mipCoord.h += 32; // 8x8
838 break;
839 case 2:
840 mipCoord.h += 32; // 4x4
841 mipCoord.w += 16;
842 break;
843 case 3:
844 mipCoord.h += 32; // 2x2
845 mipCoord.w += 32;
846 break;
847 case 4:
848 mipCoord.h += 32; // 1x1
849 mipCoord.w += 48;
850 break;
851 // The following are for BC/ASTC formats
852 case 5:
853 mipCoord.h += 48; // 1/2 x 1/2
854 break;
855 case 6:
856 mipCoord.h += 48; // 1/4 x 1/4
857 mipCoord.w += 16;
858 break;
859 case 7:
860 mipCoord.h += 48; // 1/8 x 1/8
861 mipCoord.w += 32;
862 break;
863 case 8:
864 mipCoord.h += 48; // 1/16 x 1/16
865 mipCoord.w += 48;
866 break;
867 default:
868 ADDR_ASSERT_ALWAYS();
869 break;
870 }
871
872 mipWidth = ((mip - blk32MipId) == 0) ? 16 : 8;
873 mipHeight = mipWidth;
874
875 if (isThick)
876 {
877 mipDepth = mipWidth;
878 }
879 }
880 else
881 {
882 if (mipWidth <= minInc)
883 {
884 // if we're below the minimal increment...
885 if (isThick)
886 {
887 // For 3d, just go in z direction
888 mipCoord.d += mipDepth;
889 }
890 else
891 {
892 // For 2d, first go across, then down
893 if ((mipWidth * 2) == minInc)
894 {
895 // if we're 2 mips below, that's when we go back in x, and down in y
896 mipCoord.w -= minInc;
897 mipCoord.h += minInc;
898 }
899 else
900 {
901 // otherwise, just go across in x
902 mipCoord.w += minInc;
903 }
904 }
905 }
906 else
907 {
908 // On even mip, go down, otherwise, go across
909 if (mip & 1)
910 {
911 mipCoord.w += mipWidth;
912 }
913 else
914 {
915 mipCoord.h += mipHeight;
916 }
917 }
918 // Divide the width by 2
919 mipWidth >>= 1;
920 // After the first mip in tail, the mip is always a square
921 mipHeight = mipWidth;
922 // ...or for 3d, a cube
923 if (isThick)
924 {
925 mipDepth = mipWidth;
926 }
927 }
928 }
929 }
930
931 /**
932 ****************************************************************************************************
933 * Lib::ComputeDccInfo
934 *
935 * @brief
936 * Interface function to compute DCC key info
937 *
938 * @return
939 * return code of HwlComputeDccInfo
940 ****************************************************************************************************
941 */
942 ADDR_E_RETURNCODE Lib::ComputeDccInfo(
943 const ADDR2_COMPUTE_DCCINFO_INPUT* pIn, ///< [in] input structure
944 ADDR2_COMPUTE_DCCINFO_OUTPUT* pOut ///< [out] output structure
945 ) const
946 {
947 ADDR_E_RETURNCODE returnCode;
948
949 if ((GetFillSizeFieldsFlags() == TRUE) &&
950 ((pIn->size != sizeof(ADDR2_COMPUTE_DCCINFO_INPUT)) ||
951 (pOut->size != sizeof(ADDR2_COMPUTE_DCCINFO_OUTPUT))))
952 {
953 returnCode = ADDR_INVALIDPARAMS;
954 }
955 else
956 {
957 returnCode = HwlComputeDccInfo(pIn, pOut);
958 }
959
960 return returnCode;
961 }
962
963 /**
964 ****************************************************************************************************
965 * Lib::ComputePipeBankXor
966 *
967 * @brief
968 * Interface function stub of Addr2ComputePipeBankXor.
969 *
970 * @return
971 * ADDR_E_RETURNCODE
972 ****************************************************************************************************
973 */
974 ADDR_E_RETURNCODE Lib::ComputePipeBankXor(
975 const ADDR2_COMPUTE_PIPEBANKXOR_INPUT* pIn,
976 ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT* pOut)
977 {
978 ADDR_E_RETURNCODE returnCode;
979
980 if ((GetFillSizeFieldsFlags() == TRUE) &&
981 ((pIn->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_INPUT)) ||
982 (pOut->size != sizeof(ADDR2_COMPUTE_PIPEBANKXOR_OUTPUT))))
983 {
984 returnCode = ADDR_INVALIDPARAMS;
985 }
986 else
987 {
988 UINT_32 macroBlockBits = GetBlockSizeLog2(pIn->swizzleMode);
989 UINT_32 pipeBits = GetPipeXorBits(macroBlockBits);
990 UINT_32 bankBits = GetBankXorBits(macroBlockBits);
991 UINT_32 pipeXor = 0;
992 UINT_32 bankXor = 0;
993
994 if (bankBits > 0)
995 {
996 UINT_32 bankMask = (1 << bankBits) - 1;
997 UINT_32 bankIncrease = (1 << (bankBits - 1)) - 1;
998 bankIncrease = (bankIncrease == 0) ? 1 : bankIncrease;
999 bankXor = ((pIn->surfIndex & bankMask) * bankIncrease) & bankMask;
1000 }
1001
1002 if (pipeBits > 0)
1003 {
1004 UINT_32 pipeMask = (1 << pipeBits) - 1;
1005 UINT_32 pipeIncrease = ((1 << (pipeBits - 1)) + 1) & pipeMask;
1006 pipeIncrease = (pipeIncrease == 0) ? 1 : pipeIncrease;
1007 pipeXor = ((pIn->surfIndex & pipeMask) * pipeIncrease) & pipeMask;
1008 }
1009
1010 // Todo - pOut->pipeBankXor = pOut->pipeBankXor << (PipeInterleaveLog2 - 8)
1011 pOut->pipeBankXor = (bankXor << pipeBits) | pipeXor;
1012
1013 returnCode = ADDR_OK;
1014 }
1015
1016 return returnCode;
1017 }
1018
1019 /**
1020 ****************************************************************************************************
1021 * Lib::ExtractPipeBankXor
1022 *
1023 * @brief
1024 * Internal function to extract bank and pipe xor bits from combined xor bits.
1025 *
1026 * @return
1027 * ADDR_E_RETURNCODE
1028 ****************************************************************************************************
1029 */
1030 ADDR_E_RETURNCODE Lib::ExtractPipeBankXor(
1031 UINT_32 pipeBankXor,
1032 UINT_32 bankBits,
1033 UINT_32 pipeBits,
1034 UINT_32* pBankX,
1035 UINT_32* pPipeX)
1036 {
1037 ADDR_E_RETURNCODE returnCode;
1038
1039 if (pipeBankXor < (1u << (pipeBits + bankBits)))
1040 {
1041 *pPipeX = pipeBankXor % (1 << pipeBits);
1042 *pBankX = pipeBankXor >> pipeBits;
1043 returnCode = ADDR_OK;
1044 }
1045 else
1046 {
1047 ADDR_ASSERT_ALWAYS();
1048 returnCode = ADDR_INVALIDPARAMS;
1049 }
1050
1051 return returnCode;
1052 }
1053
1054 /**
1055 ****************************************************************************************************
1056 * Lib::ComputeSurfaceInfoSanityCheck
1057 *
1058 * @brief
1059 * Internal function to do basic sanity check before compute surface info
1060 *
1061 * @return
1062 * ADDR_E_RETURNCODE
1063 ****************************************************************************************************
1064 */
1065 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoSanityCheck(
1066 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn ///< [in] input structure
1067 ) const
1068 {
1069 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1070
1071 BOOL_32 invalid = FALSE;
1072
1073 if ((pIn->bpp > 128) || (pIn->width == 0) || (pIn->numFrags > 8) || (pIn->numSamples > 16))
1074 {
1075 invalid = TRUE;
1076 }
1077 else if ((pIn->swizzleMode >= ADDR_SW_MAX_TYPE) ||
1078 (pIn->resourceType >= ADDR_RSRC_MAX_TYPE))
1079 {
1080 invalid = TRUE;
1081 }
1082
1083 BOOL_32 mipmap = (pIn->numMipLevels > 1);
1084 BOOL_32 msaa = (pIn->numFrags > 1);
1085
1086 ADDR2_SURFACE_FLAGS flags = pIn->flags;
1087 BOOL_32 zbuffer = (flags.depth || flags.stencil);
1088 BOOL_32 color = flags.color;
1089 BOOL_32 display = flags.display || flags.rotated;
1090
1091 AddrResourceType rsrcType = pIn->resourceType;
1092 BOOL_32 tex3d = IsTex3d(rsrcType);
1093
1094 AddrSwizzleMode swizzle = pIn->swizzleMode;
1095 BOOL_32 linear = IsLinear(swizzle);
1096 BOOL_32 blk256B = IsBlock256b(swizzle);
1097 BOOL_32 blkVar = IsBlockVariable(swizzle);
1098 BOOL_32 isNonPrtXor = IsNonPrtXor(swizzle);
1099 BOOL_32 prt = pIn->flags.prt;
1100
1101 if (invalid == FALSE)
1102 {
1103 if ((pIn->numFrags > 1) &&
1104 (GetBlockSize(swizzle) < (m_pipeInterleaveBytes * pIn->numFrags)))
1105 {
1106 // MSAA surface must have blk_bytes/pipe_interleave >= num_samples
1107 invalid = TRUE;
1108 }
1109 }
1110
1111 if (invalid == FALSE)
1112 {
1113 switch (rsrcType)
1114 {
1115 case ADDR_RSRC_TEX_1D:
1116 invalid = msaa || zbuffer || display || (linear == FALSE);
1117 break;
1118 case ADDR_RSRC_TEX_2D:
1119 invalid = msaa && mipmap;
1120 break;
1121 case ADDR_RSRC_TEX_3D:
1122 invalid = msaa || zbuffer || display;
1123 break;
1124 default:
1125 invalid = TRUE;
1126 break;
1127 }
1128 }
1129
1130 if (invalid == FALSE)
1131 {
1132 if (display)
1133 {
1134 invalid = (IsValidDisplaySwizzleMode(pIn) == FALSE);
1135 }
1136 }
1137
1138 if (invalid == FALSE)
1139 {
1140 if (linear)
1141 {
1142 invalid = prt || zbuffer || msaa || (pIn->bpp == 0) || ((pIn->bpp % 8) != 0);
1143 }
1144 else
1145 {
1146 if (blk256B || blkVar || isNonPrtXor)
1147 {
1148 invalid = prt;
1149 if (blk256B)
1150 {
1151 invalid = invalid || zbuffer || tex3d || mipmap || msaa;
1152 }
1153 }
1154
1155 if (invalid == FALSE)
1156 {
1157 if (IsZOrderSwizzle(swizzle))
1158 {
1159 invalid = color && msaa;
1160 }
1161 else if (IsStandardSwizzle(rsrcType, swizzle))
1162 {
1163 invalid = zbuffer;
1164 }
1165 else if (IsDisplaySwizzle(rsrcType, swizzle))
1166 {
1167 invalid = zbuffer;
1168 }
1169 else if (IsRotateSwizzle(swizzle))
1170 {
1171 invalid = zbuffer || (pIn->bpp > 64);
1172 }
1173 else
1174 {
1175 ADDR_ASSERT(!"invalid swizzle mode");
1176 invalid = TRUE;
1177 }
1178 }
1179 }
1180 }
1181
1182 if (invalid)
1183 {
1184 returnCode = ADDR_INVALIDPARAMS;
1185 }
1186
1187 return returnCode;
1188 }
1189
1190 /**
1191 ****************************************************************************************************
1192 * Lib::ApplyCustomizedPitchHeight
1193 *
1194 * @brief
1195 * Helper function to override hw required row pitch/slice pitch by customrized one
1196 *
1197 * @return
1198 * ADDR_E_RETURNCODE
1199 ****************************************************************************************************
1200 */
1201 ADDR_E_RETURNCODE Lib::ApplyCustomizedPitchHeight(
1202 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1203 UINT_32 elementBytes, ///< [in] element bytes per element
1204 UINT_32 widthAlignInElement, ///< [in] pitch alignment in element
1205 UINT_32* pPitch, ///< [in/out] pitch
1206 UINT_32* pHeight ///< [in/out] height
1207 ) const
1208 {
1209 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1210
1211 if (pIn->numMipLevels <= 1)
1212 {
1213 if (pIn->pitchInElement > 0)
1214 {
1215 if ((pIn->pitchInElement % widthAlignInElement) != 0)
1216 {
1217 returnCode = ADDR_INVALIDPARAMS;
1218 }
1219 else if (pIn->pitchInElement < (*pPitch))
1220 {
1221 returnCode = ADDR_INVALIDPARAMS;
1222 }
1223 else
1224 {
1225 *pPitch = pIn->pitchInElement;
1226 }
1227 }
1228
1229 if (returnCode == ADDR_OK)
1230 {
1231 if (pIn->sliceAlign > 0)
1232 {
1233 UINT_32 customizedHeight = pIn->sliceAlign / elementBytes / (*pPitch);
1234
1235 if (customizedHeight * elementBytes * (*pPitch) != pIn->sliceAlign)
1236 {
1237 returnCode = ADDR_INVALIDPARAMS;
1238 }
1239 else if ((pIn->numSlices > 1) && ((*pHeight) != customizedHeight))
1240 {
1241 returnCode = ADDR_INVALIDPARAMS;
1242 }
1243 else
1244 {
1245 *pHeight = customizedHeight;
1246 }
1247 }
1248 }
1249 }
1250
1251 return returnCode;
1252 }
1253
1254 /**
1255 ****************************************************************************************************
1256 * Lib::ComputeSurfaceInfoLinear
1257 *
1258 * @brief
1259 * Internal function to calculate alignment for linear swizzle surface
1260 *
1261 * @return
1262 * ADDR_E_RETURNCODE
1263 ****************************************************************************************************
1264 */
1265 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoLinear(
1266 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1267 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
1268 ) const
1269 {
1270 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1271
1272 UINT_32 pitch = 0;
1273 UINT_32 actualHeight = 0;
1274 UINT_32 elementBytes = pIn->bpp >> 3;
1275
1276 if (IsTex1d(pIn->resourceType))
1277 {
1278 if (pIn->height > 1)
1279 {
1280 returnCode = ADDR_INVALIDPARAMS;
1281 }
1282 else
1283 {
1284 const UINT_32 widthAlignInElement = 256 / elementBytes;
1285 pitch = PowTwoAlign(pIn->width, widthAlignInElement);
1286 actualHeight = pIn->numMipLevels;
1287 returnCode = ApplyCustomizedPitchHeight(pIn, elementBytes, widthAlignInElement,
1288 &pitch, &actualHeight);
1289
1290 if (returnCode == ADDR_OK)
1291 {
1292 if (pOut->pMipInfo != NULL)
1293 {
1294 for (UINT_32 i = 0; i < pIn->numMipLevels; i++)
1295 {
1296 pOut->pMipInfo[i].offset = pitch * elementBytes * i;
1297 pOut->pMipInfo[i].pitch = pitch;
1298 pOut->pMipInfo[i].height = 1;
1299 pOut->pMipInfo[i].depth = 1;
1300 }
1301 }
1302 }
1303 }
1304 }
1305 else
1306 {
1307 returnCode = ComputeSurfaceLinearPadding(pIn, &pitch, &actualHeight, pOut->pMipInfo);
1308 }
1309
1310 if ((pitch == 0) || (actualHeight == 0))
1311 {
1312 returnCode = ADDR_INVALIDPARAMS;
1313 }
1314
1315 if (returnCode == ADDR_OK)
1316 {
1317 pOut->pitch = pitch;
1318 pOut->height = pIn->height;
1319 pOut->numSlices = pIn->numSlices;
1320 pOut->mipChainPitch = pitch;
1321 pOut->mipChainHeight = actualHeight;
1322 pOut->mipChainSlice = pOut->numSlices;
1323 pOut->epitchIsHeight = (pIn->numMipLevels > 1) ? TRUE : FALSE;
1324 pOut->sliceSize = pOut->pitch * actualHeight * elementBytes;
1325 pOut->surfSize = pOut->sliceSize * pOut->numSlices;
1326 pOut->baseAlign = (pIn->swizzleMode == ADDR_SW_LINEAR_GENERAL) ? (pIn->bpp / 8) : 256;
1327 pOut->blockWidth = (pIn->swizzleMode == ADDR_SW_LINEAR_GENERAL) ? 1 : (256 * 8 / pIn->bpp);
1328 pOut->blockHeight = 1;
1329 pOut->blockSlices = 1;
1330 }
1331
1332 // Post calculation validate
1333 ADDR_ASSERT((pOut->sliceSize > 0));
1334
1335 return returnCode;
1336 }
1337
1338 /**
1339 ****************************************************************************************************
1340 * Lib::ComputeSurfaceInfoTiled
1341 *
1342 * @brief
1343 * Internal function to calculate alignment for tiled swizzle surface
1344 *
1345 * @return
1346 * ADDR_E_RETURNCODE
1347 ****************************************************************************************************
1348 */
1349 ADDR_E_RETURNCODE Lib::ComputeSurfaceInfoTiled(
1350 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input structure
1351 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT* pOut ///< [out] output structure
1352 ) const
1353 {
1354 ADDR_E_RETURNCODE returnCode = ComputeBlockDimensionForSurf(&pOut->blockWidth,
1355 &pOut->blockHeight,
1356 &pOut->blockSlices,
1357 pIn->bpp,
1358 pIn->numFrags,
1359 pIn->resourceType,
1360 pIn->swizzleMode);
1361
1362 if (returnCode == ADDR_OK)
1363 {
1364 const UINT_32 widthAlignInElement = pOut->blockWidth;
1365
1366 pOut->pitch = PowTwoAlign(pIn->width, widthAlignInElement);
1367
1368 if ((pIn->numMipLevels <= 1) && (pIn->pitchInElement > 0))
1369 {
1370 if ((pIn->pitchInElement % widthAlignInElement) != 0)
1371 {
1372 returnCode = ADDR_INVALIDPARAMS;
1373 }
1374 else if (pIn->pitchInElement < pOut->pitch)
1375 {
1376 returnCode = ADDR_INVALIDPARAMS;
1377 }
1378 else
1379 {
1380 pOut->pitch = pIn->pitchInElement;
1381 }
1382 }
1383
1384 if (returnCode == ADDR_OK)
1385 {
1386 pOut->height = PowTwoAlign(pIn->height, pOut->blockHeight);
1387 pOut->numSlices = PowTwoAlign(pIn->numSlices, pOut->blockSlices);
1388
1389 pOut->epitchIsHeight = FALSE;
1390 pOut->firstMipInTail = FALSE;
1391
1392 pOut->mipChainPitch = pOut->pitch;
1393 pOut->mipChainHeight = pOut->height;
1394 pOut->mipChainSlice = pOut->numSlices;
1395
1396 if (pIn->numMipLevels > 1)
1397 {
1398 UINT_32 numMipLevel;
1399 ADDR2_MIP_INFO *pMipInfo;
1400 ADDR2_MIP_INFO mipInfo[4];
1401
1402 if (pOut->pMipInfo != NULL)
1403 {
1404 pMipInfo = pOut->pMipInfo;
1405 numMipLevel = pIn->numMipLevels;
1406 }
1407 else
1408 {
1409 pMipInfo = mipInfo;
1410 numMipLevel = Min(pIn->numMipLevels, 4u);
1411 }
1412
1413 UINT_32 endingMip = GetMipChainInfo(pIn->resourceType,
1414 pIn->swizzleMode,
1415 pIn->bpp,
1416 pIn->width,
1417 pIn->height,
1418 pIn->numSlices,
1419 pOut->blockWidth,
1420 pOut->blockHeight,
1421 pOut->blockSlices,
1422 numMipLevel,
1423 pMipInfo);
1424
1425 if (endingMip == 0)
1426 {
1427 pOut->epitchIsHeight = TRUE;
1428 pOut->pitch = pMipInfo[0].pitch;
1429 pOut->height = pMipInfo[0].height;
1430 pOut->numSlices = pMipInfo[0].depth;
1431 pOut->firstMipInTail = TRUE;
1432 }
1433 else
1434 {
1435 UINT_32 mip0WidthInBlk = pOut->pitch / pOut->blockWidth;
1436 UINT_32 mip0HeightInBlk = pOut->height / pOut->blockHeight;
1437
1438 AddrMajorMode majorMode = GetMajorMode(pIn->resourceType,
1439 pIn->swizzleMode,
1440 mip0WidthInBlk,
1441 mip0HeightInBlk,
1442 pOut->numSlices / pOut->blockSlices);
1443 if (majorMode == ADDR_MAJOR_Y)
1444 {
1445 UINT_32 mip1WidthInBlk = RoundHalf(mip0WidthInBlk);
1446
1447 if ((mip1WidthInBlk == 1) && (endingMip > 2))
1448 {
1449 mip1WidthInBlk++;
1450 }
1451
1452 pOut->mipChainPitch += (mip1WidthInBlk * pOut->blockWidth);
1453
1454 pOut->epitchIsHeight = FALSE;
1455 }
1456 else
1457 {
1458 UINT_32 mip1HeightInBlk = RoundHalf(mip0HeightInBlk);
1459
1460 if ((mip1HeightInBlk == 1) && (endingMip > 2))
1461 {
1462 mip1HeightInBlk++;
1463 }
1464
1465 pOut->mipChainHeight += (mip1HeightInBlk * pOut->blockHeight);
1466
1467 pOut->epitchIsHeight = TRUE;
1468 }
1469 }
1470 }
1471 else if (pOut->pMipInfo != NULL)
1472 {
1473 pOut->pMipInfo[0].pitch = pOut->pitch;
1474 pOut->pMipInfo[0].height = pOut->height;
1475 pOut->pMipInfo[0].depth = IsTex3d(pIn->resourceType)? pOut->numSlices : 1;
1476 pOut->pMipInfo[0].offset = 0;
1477 }
1478
1479 pOut->sliceSize = pOut->mipChainPitch *pOut->mipChainHeight *
1480 (pIn->bpp >> 3) * pIn->numFrags;
1481 pOut->surfSize = pOut->sliceSize * pOut->mipChainSlice;
1482 pOut->baseAlign = ComputeSurfaceBaseAlign(pIn->swizzleMode);
1483 }
1484 }
1485
1486 return returnCode;
1487 }
1488
1489 /**
1490 ****************************************************************************************************
1491 * Lib::ComputeSurfaceAddrFromCoordLinear
1492 *
1493 * @brief
1494 * Internal function to calculate address from coord for linear swizzle surface
1495 *
1496 * @return
1497 * ADDR_E_RETURNCODE
1498 ****************************************************************************************************
1499 */
1500 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordLinear(
1501 const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
1502 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
1503 ) const
1504 {
1505 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1506 BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1) && (pIn->pipeBankXor == 0);
1507
1508 if (valid)
1509 {
1510 if (IsTex1d(pIn->resourceType))
1511 {
1512 valid = (pIn->y == 0);
1513 }
1514 }
1515
1516 if (valid)
1517 {
1518 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
1519 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1520 localIn.bpp = pIn->bpp;
1521 localIn.width = Max(pIn->unalignedWidth, 1u);
1522 localIn.height = Max(pIn->unalignedHeight, 1u);
1523 localIn.numSlices = Max(pIn->numSlices, 1u);
1524 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1525 localIn.resourceType = pIn->resourceType;
1526 if (localIn.numMipLevels <= 1)
1527 {
1528 localIn.pitchInElement = pIn->pitchInElement;
1529 }
1530 returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1531
1532 if (returnCode == ADDR_OK)
1533 {
1534 UINT_32 elementBytes = pIn->bpp >> 3;
1535 UINT_64 sliceOffsetInSurf = static_cast<UINT_64>(pIn->slice) * localOut.sliceSize;
1536 UINT_64 mipOffsetInSlice = 0;
1537 UINT_64 offsetInMip = 0;
1538
1539 if (IsTex1d(pIn->resourceType))
1540 {
1541 offsetInMip = static_cast<UINT_64>(pIn->x) * elementBytes;
1542 mipOffsetInSlice = static_cast<UINT_64>(pIn->mipId) * localOut.pitch * elementBytes;
1543 }
1544 else
1545 {
1546 UINT_64 mipStartHeight = SumGeo(localIn.height, pIn->mipId);
1547 mipOffsetInSlice = static_cast<UINT_64>(mipStartHeight) * localOut.pitch * elementBytes;
1548 offsetInMip = (pIn->y * localOut.pitch + pIn->x) * elementBytes;
1549 }
1550
1551 pOut->addr = sliceOffsetInSurf + mipOffsetInSlice + offsetInMip;
1552 pOut->bitPosition = 0;
1553 }
1554 else
1555 {
1556 valid = FALSE;
1557 }
1558 }
1559
1560 if (valid == FALSE)
1561 {
1562 returnCode = ADDR_INVALIDPARAMS;
1563 }
1564
1565 return returnCode;
1566 }
1567
1568 /**
1569 ****************************************************************************************************
1570 * Lib::ComputeSurfaceAddrFromCoordTiled
1571 *
1572 * @brief
1573 * Internal function to calculate address from coord for tiled swizzle surface
1574 *
1575 * @return
1576 * ADDR_E_RETURNCODE
1577 ****************************************************************************************************
1578 */
1579 ADDR_E_RETURNCODE Lib::ComputeSurfaceAddrFromCoordTiled(
1580 const ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn, ///< [in] input structure
1581 ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_OUTPUT* pOut ///< [out] output structure
1582 ) const
1583 {
1584 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
1585 localIn.swizzleMode = pIn->swizzleMode;
1586 localIn.flags = pIn->flags;
1587 localIn.resourceType = pIn->resourceType;
1588 localIn.bpp = pIn->bpp;
1589 localIn.width = Max(pIn->unalignedWidth, 1u);
1590 localIn.height = Max(pIn->unalignedHeight, 1u);
1591 localIn.numSlices = Max(pIn->numSlices, 1u);
1592 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1593 if (localIn.numMipLevels <= 1)
1594 {
1595 localIn.pitchInElement = pIn->pitchInElement;
1596 }
1597
1598 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1599 ADDR_E_RETURNCODE returnCode = ComputeSurfaceInfoTiled(&localIn, &localOut);
1600
1601 BOOL_32 valid = (returnCode == ADDR_OK) &&
1602 (IsThin(pIn->resourceType, pIn->swizzleMode) ||
1603 IsThick(pIn->resourceType, pIn->swizzleMode)) &&
1604 ((pIn->pipeBankXor == 0) || (IsXor(pIn->swizzleMode)));
1605
1606 if (valid)
1607 {
1608 Dim3d mipStartPos = {0};
1609 UINT_32 mipTailOffset = 0;
1610
1611 if (pIn->numMipLevels > 1)
1612 {
1613 // Mip-map chain cannot be MSAA surface
1614 ADDR_ASSERT((pIn->numSamples <= 1) && (pIn->numFrags<= 1));
1615
1616 mipStartPos = GetMipStartPos(pIn->resourceType,
1617 pIn->swizzleMode,
1618 localOut.pitch,
1619 localOut.height,
1620 localOut.numSlices,
1621 localOut.blockWidth,
1622 localOut.blockHeight,
1623 localOut.blockSlices,
1624 pIn->mipId,
1625 &mipTailOffset);
1626 }
1627
1628 UINT_32 interleaveOffset = 0;
1629 UINT_32 pipeBits = 0;
1630 UINT_32 pipeXor = 0;
1631 UINT_32 bankBits = 0;
1632 UINT_32 bankXor = 0;
1633
1634 if (IsThin(pIn->resourceType, pIn->swizzleMode))
1635 {
1636 UINT_32 blockOffset = 0;
1637 UINT_32 log2blkSize = GetBlockSizeLog2(pIn->swizzleMode);
1638 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1639
1640 if (IsZOrderSwizzle(pIn->swizzleMode))
1641 {
1642 // Morton generation
1643 if ((log2ElementBytes == 0) || (log2ElementBytes == 2))
1644 {
1645 UINT_32 totalLowBits = 6 - log2ElementBytes;
1646 UINT_32 mortBits = totalLowBits / 2;
1647 UINT_32 lowBitsValue = MortonGen2d(pIn->y, pIn->x, mortBits);
1648 // Are 9 bits enough?
1649 UINT_32 highBitsValue =
1650 MortonGen2d(pIn->x >> mortBits, pIn->y >> mortBits, 9) << totalLowBits;
1651 blockOffset = lowBitsValue | highBitsValue;
1652 ADDR_ASSERT(blockOffset == lowBitsValue + highBitsValue);
1653 }
1654 else
1655 {
1656 blockOffset = MortonGen2d(pIn->y, pIn->x, 13);
1657 }
1658
1659 // Fill LSBs with sample bits
1660 if (pIn->numSamples > 1)
1661 {
1662 blockOffset *= pIn->numSamples;
1663 blockOffset |= pIn->sample;
1664 }
1665
1666 // Shift according to BytesPP
1667 blockOffset <<= log2ElementBytes;
1668 }
1669 else
1670 {
1671 // Micro block offset
1672 UINT_32 microBlockOffset = ComputeSurface2DMicroBlockOffset(pIn);
1673 blockOffset = microBlockOffset;
1674
1675 // Micro block dimension
1676 ADDR_ASSERT(log2ElementBytes < sizeof(Block256b) / sizeof(Block256b[0]));
1677 Dim2d microBlockDim = Block256b[log2ElementBytes];
1678 // Morton generation, does 12 bit enough?
1679 blockOffset |=
1680 MortonGen2d((pIn->x / microBlockDim.w), (pIn->y / microBlockDim.h), 12) << 8;
1681
1682 // Sample bits start location
1683 UINT_32 sampleStart = log2blkSize - Log2(pIn->numSamples);
1684 // Join sample bits information to the highest Macro block bits
1685 if (IsNonPrtXor(pIn->swizzleMode))
1686 {
1687 // Non-prt-Xor : xor highest Macro block bits with sample bits
1688 blockOffset = blockOffset ^ (pIn->sample << sampleStart);
1689 }
1690 else
1691 {
1692 // Non-Xor or prt-Xor: replace highest Macro block bits with sample bits
1693 // after this op, the blockOffset only contains log2 Macro block size bits
1694 blockOffset %= (1 << sampleStart);
1695 blockOffset |= (pIn->sample << sampleStart);
1696 ADDR_ASSERT((blockOffset >> log2blkSize) == 0);
1697 }
1698 }
1699
1700 if (IsXor(pIn->swizzleMode))
1701 {
1702 // Mask off bits above Macro block bits to keep page synonyms working for prt
1703 if (IsPrt(pIn->swizzleMode))
1704 {
1705 blockOffset &= ((1 << log2blkSize) - 1);
1706 }
1707
1708 // Preserve offset inside pipe interleave
1709 interleaveOffset = blockOffset & ((1 << m_pipeInterleaveLog2) - 1);
1710 blockOffset >>= m_pipeInterleaveLog2;
1711
1712 // Pipe/Se xor bits
1713 pipeBits = GetPipeXorBits(log2blkSize);
1714 // Pipe xor
1715 pipeXor = FoldXor2d(blockOffset, pipeBits);
1716 blockOffset >>= pipeBits;
1717
1718 // Bank xor bits
1719 bankBits = GetBankXorBits(log2blkSize);
1720 // Bank Xor
1721 bankXor = FoldXor2d(blockOffset, bankBits);
1722 blockOffset >>= bankBits;
1723
1724 // Put all the part back together
1725 blockOffset <<= bankBits;
1726 blockOffset |= bankXor;
1727 blockOffset <<= pipeBits;
1728 blockOffset |= pipeXor;
1729 blockOffset <<= m_pipeInterleaveLog2;
1730 blockOffset |= interleaveOffset;
1731 }
1732
1733 ADDR_ASSERT((blockOffset | mipTailOffset) == (blockOffset + mipTailOffset));
1734 blockOffset |= mipTailOffset;
1735
1736 if (IsNonPrtXor(pIn->swizzleMode) && (pIn->numSamples <= 1))
1737 {
1738 // Apply slice xor if not MSAA/PRT
1739 blockOffset ^= (ReverseBitVector(pIn->slice, pipeBits) << m_pipeInterleaveLog2);
1740 blockOffset ^= (ReverseBitVector(pIn->slice >> pipeBits, bankBits) <<
1741 (m_pipeInterleaveLog2 + pipeBits));
1742 }
1743
1744 returnCode = ApplyCustomerPipeBankXor(pIn->swizzleMode, pIn->pipeBankXor,
1745 bankBits, pipeBits, &blockOffset);
1746
1747 blockOffset %= (1 << log2blkSize);
1748
1749 UINT_32 pitchInMacroBlock = localOut.mipChainPitch / localOut.blockWidth;
1750 UINT_32 paddedHeightInMacroBlock = localOut.mipChainHeight / localOut.blockHeight;
1751 UINT_32 sliceSizeInMacroBlock = pitchInMacroBlock * paddedHeightInMacroBlock;
1752 UINT_32 macroBlockIndex =
1753 (pIn->slice + mipStartPos.d) * sliceSizeInMacroBlock +
1754 ((pIn->y / localOut.blockHeight) + mipStartPos.h) * pitchInMacroBlock +
1755 ((pIn->x / localOut.blockWidth) + mipStartPos.w);
1756
1757 UINT_64 macroBlockOffset = (static_cast<UINT_64>(macroBlockIndex) <<
1758 GetBlockSizeLog2(pIn->swizzleMode));
1759
1760 pOut->addr = blockOffset | macroBlockOffset;
1761 }
1762 else
1763 {
1764 UINT_32 log2blkSize = GetBlockSizeLog2(pIn->swizzleMode);
1765 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
1766
1767 Dim3d microBlockDim = Block1kb[log2ElementBytes];
1768
1769 UINT_32 blockOffset = MortonGen3d((pIn->x / microBlockDim.w),
1770 (pIn->y / microBlockDim.h),
1771 (pIn->slice / microBlockDim.d),
1772 8);
1773
1774 blockOffset <<= 10;
1775 blockOffset |= ComputeSurface3DMicroBlockOffset(pIn);
1776
1777 if (IsXor(pIn->swizzleMode))
1778 {
1779 // Mask off bits above Macro block bits to keep page synonyms working for prt
1780 if (IsPrt(pIn->swizzleMode))
1781 {
1782 blockOffset &= ((1 << log2blkSize) - 1);
1783 }
1784
1785 // Preserve offset inside pipe interleave
1786 interleaveOffset = blockOffset & ((1 << m_pipeInterleaveLog2) - 1);
1787 blockOffset >>= m_pipeInterleaveLog2;
1788
1789 // Pipe/Se xor bits
1790 pipeBits = GetPipeXorBits(log2blkSize);
1791 // Pipe xor
1792 pipeXor = FoldXor3d(blockOffset, pipeBits);
1793 blockOffset >>= pipeBits;
1794
1795 // Bank xor bits
1796 bankBits = GetBankXorBits(log2blkSize);
1797 // Bank Xor
1798 bankXor = FoldXor3d(blockOffset, bankBits);
1799 blockOffset >>= bankBits;
1800
1801 // Put all the part back together
1802 blockOffset <<= bankBits;
1803 blockOffset |= bankXor;
1804 blockOffset <<= pipeBits;
1805 blockOffset |= pipeXor;
1806 blockOffset <<= m_pipeInterleaveLog2;
1807 blockOffset |= interleaveOffset;
1808 }
1809
1810 ADDR_ASSERT((blockOffset | mipTailOffset) == (blockOffset + mipTailOffset));
1811 blockOffset |= mipTailOffset;
1812
1813 returnCode = ApplyCustomerPipeBankXor(pIn->swizzleMode, pIn->pipeBankXor,
1814 bankBits, pipeBits, &blockOffset);
1815
1816 blockOffset %= (1 << log2blkSize);
1817
1818 UINT_32 xb = (pIn->x + mipStartPos.w) / localOut.blockWidth;
1819 UINT_32 yb = (pIn->y + mipStartPos.h) / localOut.blockHeight;
1820 UINT_32 zb = (pIn->slice + mipStartPos.d) / localOut.blockSlices;
1821
1822 UINT_32 pitchInBlock = localOut.mipChainPitch / localOut.blockWidth;
1823 UINT_32 sliceSizeInBlock =
1824 (localOut.mipChainHeight / localOut.blockHeight) * pitchInBlock;
1825 UINT_32 blockIndex = zb * sliceSizeInBlock + yb * pitchInBlock + xb;
1826
1827 pOut->addr = blockOffset | (blockIndex << log2blkSize);
1828 }
1829 }
1830 else
1831 {
1832 returnCode = ADDR_INVALIDPARAMS;
1833 }
1834
1835 return returnCode;
1836 }
1837
1838 /**
1839 ****************************************************************************************************
1840 * Lib::ComputeSurfaceCoordFromAddrLinear
1841 *
1842 * @brief
1843 * Internal function to calculate coord from address for linear swizzle surface
1844 *
1845 * @return
1846 * ADDR_E_RETURNCODE
1847 ****************************************************************************************************
1848 */
1849 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrLinear(
1850 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
1851 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
1852 ) const
1853 {
1854 ADDR_E_RETURNCODE returnCode = ADDR_OK;
1855
1856 BOOL_32 valid = (pIn->numSamples <= 1) && (pIn->numFrags <= 1);
1857
1858 if (valid)
1859 {
1860 if (IsTex1d(pIn->resourceType))
1861 {
1862 valid = (pIn->unalignedHeight == 1);
1863 }
1864 }
1865
1866 if (valid)
1867 {
1868 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
1869 ADDR2_COMPUTE_SURFACE_INFO_OUTPUT localOut = {0};
1870 localIn.bpp = pIn->bpp;
1871 localIn.width = Max(pIn->unalignedWidth, 1u);
1872 localIn.height = Max(pIn->unalignedHeight, 1u);
1873 localIn.numSlices = Max(pIn->numSlices, 1u);
1874 localIn.numMipLevels = Max(pIn->numMipLevels, 1u);
1875 localIn.resourceType = pIn->resourceType;
1876 if (localIn.numMipLevels <= 1)
1877 {
1878 localIn.pitchInElement = pIn->pitchInElement;
1879 }
1880 returnCode = ComputeSurfaceInfoLinear(&localIn, &localOut);
1881
1882 if (returnCode == ADDR_OK)
1883 {
1884 pOut->slice = static_cast<UINT_32>(pIn->addr / localOut.sliceSize);
1885 pOut->sample = 0;
1886
1887 UINT_32 offsetInSlice = static_cast<UINT_32>(pIn->addr % localOut.sliceSize);
1888 UINT_32 elementBytes = pIn->bpp >> 3;
1889 UINT_32 mipOffsetInSlice = 0;
1890 UINT_32 mipSize = 0;
1891 UINT_32 mipId = 0;
1892 for (; mipId < pIn->numMipLevels ; mipId++)
1893 {
1894 if (IsTex1d(pIn->resourceType))
1895 {
1896 mipSize = localOut.pitch * elementBytes;
1897 }
1898 else
1899 {
1900 UINT_32 currentMipHeight = (PowTwoAlign(localIn.height, (1 << mipId))) >> mipId;
1901 mipSize = currentMipHeight * localOut.pitch * elementBytes;
1902 }
1903
1904 if (mipSize == 0)
1905 {
1906 valid = FALSE;
1907 break;
1908 }
1909 else if ((mipSize + mipOffsetInSlice) > offsetInSlice)
1910 {
1911 break;
1912 }
1913 else
1914 {
1915 mipOffsetInSlice += mipSize;
1916 if ((mipId == (pIn->numMipLevels - 1)) ||
1917 (mipOffsetInSlice >= localOut.sliceSize))
1918 {
1919 valid = FALSE;
1920 }
1921 }
1922 }
1923
1924 if (valid)
1925 {
1926 pOut->mipId = mipId;
1927
1928 UINT_32 elemOffsetInMip = (offsetInSlice - mipOffsetInSlice) / elementBytes;
1929 if (IsTex1d(pIn->resourceType))
1930 {
1931 if (elemOffsetInMip < localOut.pitch)
1932 {
1933 pOut->x = elemOffsetInMip;
1934 pOut->y = 0;
1935 }
1936 else
1937 {
1938 valid = FALSE;
1939 }
1940 }
1941 else
1942 {
1943 pOut->y = elemOffsetInMip / localOut.pitch;
1944 pOut->x = elemOffsetInMip % localOut.pitch;
1945 }
1946
1947 if ((pOut->slice >= pIn->numSlices) ||
1948 (pOut->mipId >= pIn->numMipLevels) ||
1949 (pOut->x >= Max((pIn->unalignedWidth >> pOut->mipId), 1u)) ||
1950 (pOut->y >= Max((pIn->unalignedHeight >> pOut->mipId), 1u)) ||
1951 (IsTex3d(pIn->resourceType) &&
1952 (FALSE == Valid3DMipSliceIdConstraint(pIn->numSlices,
1953 pOut->mipId,
1954 pOut->slice))))
1955 {
1956 valid = FALSE;
1957 }
1958 }
1959 }
1960 else
1961 {
1962 valid = FALSE;
1963 }
1964 }
1965
1966 if (valid == FALSE)
1967 {
1968 returnCode = ADDR_INVALIDPARAMS;
1969 }
1970
1971 return returnCode;
1972 }
1973
1974 /**
1975 ****************************************************************************************************
1976 * Lib::ComputeSurfaceCoordFromAddrTiled
1977 *
1978 * @brief
1979 * Internal function to calculate coord from address for tiled swizzle surface
1980 *
1981 * @return
1982 * ADDR_E_RETURNCODE
1983 ****************************************************************************************************
1984 */
1985 ADDR_E_RETURNCODE Lib::ComputeSurfaceCoordFromAddrTiled(
1986 const ADDR2_COMPUTE_SURFACE_COORDFROMADDR_INPUT* pIn, ///< [in] input structure
1987 ADDR2_COMPUTE_SURFACE_COORDFROMADDR_OUTPUT* pOut ///< [out] output structure
1988 ) const
1989 {
1990 ADDR_E_RETURNCODE returnCode = ADDR_NOTIMPLEMENTED;
1991
1992 ADDR_NOT_IMPLEMENTED();
1993
1994 return returnCode;
1995 }
1996
1997 /**
1998 ****************************************************************************************************
1999 * Lib::ComputeSurfaceInfoLinear
2000 *
2001 * @brief
2002 * Internal function to calculate padding for linear swizzle 2D/3D surface
2003 *
2004 * @return
2005 * N/A
2006 ****************************************************************************************************
2007 */
2008 ADDR_E_RETURNCODE Lib::ComputeSurfaceLinearPadding(
2009 const ADDR2_COMPUTE_SURFACE_INFO_INPUT* pIn, ///< [in] input srtucture
2010 UINT_32* pMipmap0PaddedWidth, ///< [out] padded width in element
2011 UINT_32* pSlice0PaddedHeight, ///< [out] padded height for HW
2012 ADDR2_MIP_INFO* pMipInfo ///< [out] per mip information
2013 ) const
2014 {
2015 ADDR_E_RETURNCODE returnCode = ADDR_OK;
2016
2017 UINT_32 elementBytes = pIn->bpp >> 3;
2018 UINT_32 widthAlignInElement = 0;
2019
2020 if (pIn->swizzleMode == ADDR_SW_LINEAR_GENERAL)
2021 {
2022 ADDR_ASSERT(pIn->numMipLevels <= 1);
2023 ADDR_ASSERT(pIn->numSlices <= 1);
2024 widthAlignInElement = 1;
2025 }
2026 else
2027 {
2028 widthAlignInElement = (256 / elementBytes);
2029 }
2030
2031 UINT_32 mipChainWidth = PowTwoAlign(pIn->width, widthAlignInElement);
2032 UINT_32 slice0PaddedHeight = pIn->height;
2033
2034 returnCode = ApplyCustomizedPitchHeight(pIn, elementBytes, widthAlignInElement,
2035 &mipChainWidth, &slice0PaddedHeight);
2036
2037 if (returnCode == ADDR_OK)
2038 {
2039 UINT_32 mipChainHeight = 0;
2040 UINT_32 mipHeight = pIn->height;
2041
2042 for (UINT_32 i = 0; i < pIn->numMipLevels; i++)
2043 {
2044 if (pMipInfo != NULL)
2045 {
2046 pMipInfo[i].offset = mipChainWidth * mipChainHeight * elementBytes;
2047 pMipInfo[i].pitch = mipChainWidth;
2048 pMipInfo[i].height = mipHeight;
2049 pMipInfo[i].depth = 1;
2050 }
2051
2052 mipChainHeight += mipHeight;
2053 mipHeight = RoundHalf(mipHeight);
2054 mipHeight = Max(mipHeight, 1u);
2055 }
2056
2057 *pMipmap0PaddedWidth = mipChainWidth;
2058 *pSlice0PaddedHeight = (pIn->numMipLevels > 1) ? mipChainHeight : slice0PaddedHeight;
2059 }
2060
2061 return returnCode;
2062 }
2063
2064 /**
2065 ****************************************************************************************************
2066 * Lib::ComputeBlockDimensionForSurf
2067 *
2068 * @brief
2069 * Internal function to get block width/height/depth in element from surface input params.
2070 *
2071 * @return
2072 * ADDR_E_RETURNCODE
2073 ****************************************************************************************************
2074 */
2075 ADDR_E_RETURNCODE Lib::ComputeBlockDimensionForSurf(
2076 Dim3d* pDim,
2077 UINT_32 bpp,
2078 UINT_32 numSamples,
2079 AddrResourceType resourceType,
2080 AddrSwizzleMode swizzleMode) const
2081 {
2082 return ComputeBlockDimensionForSurf(&pDim->w, &pDim->h, &pDim->d, bpp,
2083 numSamples, resourceType, swizzleMode);
2084 }
2085
2086 /**
2087 ****************************************************************************************************
2088 * Lib::ComputeBlockDimensionForSurf
2089 *
2090 * @brief
2091 * Internal function to get block width/height/depth in element from surface input params.
2092 *
2093 * @return
2094 * ADDR_E_RETURNCODE
2095 ****************************************************************************************************
2096 */
2097 ADDR_E_RETURNCODE Lib::ComputeBlockDimensionForSurf(
2098 UINT_32* pWidth,
2099 UINT_32* pHeight,
2100 UINT_32* pDepth,
2101 UINT_32 bpp,
2102 UINT_32 numSamples,
2103 AddrResourceType resourceType,
2104 AddrSwizzleMode swizzleMode) const
2105 {
2106 ADDR_E_RETURNCODE returnCode = ComputeBlockDimension(pWidth,
2107 pHeight,
2108 pDepth,
2109 bpp,
2110 resourceType,
2111 swizzleMode);
2112
2113 if ((returnCode == ADDR_OK) && (numSamples > 1) && IsThin(resourceType, swizzleMode))
2114 {
2115 UINT_32 log2blkSize = GetBlockSizeLog2(swizzleMode);
2116 UINT_32 sample = numSamples;
2117 UINT_32 log2sample = Log2(sample);
2118
2119 *pWidth >>= (log2sample / 2);
2120 *pHeight >>= (log2sample / 2);
2121
2122 if ((log2blkSize % 2) == 0)
2123 {
2124 *pWidth >>= (sample % 2);
2125 }
2126 else
2127 {
2128 *pHeight >>= (sample % 2);
2129 }
2130 }
2131
2132 return returnCode;
2133 }
2134
2135 /**
2136 ****************************************************************************************************
2137 * Lib::ComputeBlockDimension
2138 *
2139 * @brief
2140 * Internal function to get block width/height/depth in element without considering MSAA case
2141 *
2142 * @return
2143 * ADDR_E_RETURNCODE
2144 ****************************************************************************************************
2145 */
2146 ADDR_E_RETURNCODE Lib::ComputeBlockDimension(
2147 UINT_32* pWidth,
2148 UINT_32* pHeight,
2149 UINT_32* pDepth,
2150 UINT_32 bpp,
2151 AddrResourceType resourceType,
2152 AddrSwizzleMode swizzleMode) const
2153 {
2154 ADDR_E_RETURNCODE returnCode = ADDR_OK;
2155
2156 UINT_32 eleBytes = bpp >> 3;
2157 UINT_32 microBlockSizeTableIndex = Log2(eleBytes);
2158 UINT_32 log2blkSize = GetBlockSizeLog2(swizzleMode);
2159
2160 if (IsThin(resourceType, swizzleMode))
2161 {
2162 if (pDepth != NULL)
2163 {
2164 *pDepth = 1;
2165 }
2166
2167 UINT_32 log2blkSizeIn256B = log2blkSize - 8;
2168 UINT_32 widthAmp = log2blkSizeIn256B / 2;
2169 UINT_32 heightAmp = log2blkSizeIn256B - widthAmp;
2170
2171 ADDR_ASSERT(microBlockSizeTableIndex < sizeof(Block256b) / sizeof(Block256b[0]));
2172
2173 *pWidth = (Block256b[microBlockSizeTableIndex].w << widthAmp);
2174 *pHeight = (Block256b[microBlockSizeTableIndex].h << heightAmp);
2175 }
2176 else if (IsThick(resourceType, swizzleMode))
2177 {
2178 UINT_32 log2blkSizeIn1KB = log2blkSize - 10;
2179 UINT_32 averageAmp = log2blkSizeIn1KB / 3;
2180 UINT_32 restAmp = log2blkSizeIn1KB % 3;
2181
2182 ADDR_ASSERT(microBlockSizeTableIndex < sizeof(Block1kb) / sizeof(Block1kb[0]));
2183
2184 *pWidth = Block1kb[microBlockSizeTableIndex].w << averageAmp;
2185 *pHeight = Block1kb[microBlockSizeTableIndex].h << (averageAmp + (restAmp / 2));
2186 *pDepth = Block1kb[microBlockSizeTableIndex].d << (averageAmp + ((restAmp != 0) ? 1 : 0));
2187 }
2188 else
2189 {
2190 ADDR_ASSERT_ALWAYS();
2191 returnCode = ADDR_INVALIDPARAMS;
2192 }
2193
2194 return returnCode;
2195 }
2196
2197 /**
2198 ****************************************************************************************************
2199 * Lib::GetMipChainInfo
2200 *
2201 * @brief
2202 * Internal function to get out information about mip chain
2203 *
2204 * @return
2205 * Smaller value between Id of first mip fitted in mip tail and max Id of mip being created
2206 ****************************************************************************************************
2207 */
2208 UINT_32 Lib::GetMipChainInfo(
2209 AddrResourceType resourceType,
2210 AddrSwizzleMode swizzleMode,
2211 UINT_32 bpp,
2212 UINT_32 mip0Width,
2213 UINT_32 mip0Height,
2214 UINT_32 mip0Depth,
2215 UINT_32 blockWidth,
2216 UINT_32 blockHeight,
2217 UINT_32 blockDepth,
2218 UINT_32 numMipLevel,
2219 ADDR2_MIP_INFO* pMipInfo) const
2220 {
2221 const Dim3d tailMaxDim =
2222 GetMipTailDim(resourceType, swizzleMode, blockWidth, blockHeight, blockDepth);
2223
2224 UINT_32 mipPitch = mip0Width;
2225 UINT_32 mipHeight = mip0Height;
2226 UINT_32 mipDepth = IsTex3d(resourceType) ? mip0Depth : 1;
2227 UINT_32 offset = 0;
2228 UINT_32 endingMip = numMipLevel - 1;
2229 BOOL_32 inTail = FALSE;
2230 BOOL_32 finalDim = FALSE;
2231
2232 BOOL_32 is3dThick = IsThick(resourceType, swizzleMode);
2233 BOOL_32 is3dThin = IsTex3d(resourceType) && SwizzleModeTable[swizzleMode].isDisp;
2234
2235 for (UINT_32 mipId = 0; mipId < numMipLevel; mipId++)
2236 {
2237 if (inTail)
2238 {
2239 if (finalDim == FALSE)
2240 {
2241 UINT_32 mipSize;
2242
2243 if (is3dThick)
2244 {
2245 mipSize = mipPitch * mipHeight * mipDepth * (bpp >> 3);
2246 }
2247 else
2248 {
2249 mipSize = mipPitch * mipHeight * (bpp >> 3);
2250 }
2251
2252 if (mipSize <= 256)
2253 {
2254 UINT_32 index = Log2(bpp >> 3);
2255
2256 if (is3dThick)
2257 {
2258 mipPitch = CompressBlock3dZ[index].w;
2259 mipHeight = CompressBlock3dZ[index].h;
2260 mipDepth = CompressBlock3dZ[index].d;
2261 }
2262 else
2263 {
2264 mipPitch = CompressBlock2d[index].w;
2265 mipHeight = CompressBlock2d[index].h;
2266 }
2267
2268 finalDim = TRUE;
2269 }
2270 }
2271 }
2272 else
2273 {
2274 inTail = IsInMipTail(resourceType, swizzleMode, tailMaxDim,
2275 mipPitch, mipHeight, mipDepth);
2276
2277 if (inTail)
2278 {
2279 endingMip = mipId;
2280
2281 mipPitch = tailMaxDim.w;
2282 mipHeight = tailMaxDim.h;
2283
2284 if (is3dThick)
2285 {
2286 mipDepth = tailMaxDim.d;
2287 }
2288 }
2289 else
2290 {
2291 mipPitch = PowTwoAlign(mipPitch, blockWidth);
2292 mipHeight = PowTwoAlign(mipHeight, blockHeight);
2293
2294 if (is3dThick)
2295 {
2296 mipDepth = PowTwoAlign(mipDepth, blockDepth);
2297 }
2298 }
2299 }
2300
2301 pMipInfo[mipId].pitch = mipPitch;
2302 pMipInfo[mipId].height = mipHeight;
2303 pMipInfo[mipId].depth = mipDepth;
2304 pMipInfo[mipId].offset = offset;
2305 offset += (mipPitch * mipHeight * mipDepth * (bpp >> 3));
2306
2307 if (finalDim)
2308 {
2309 if (is3dThin)
2310 {
2311 mipDepth = Max(mipDepth >> 1, 1u);
2312 }
2313 }
2314 else
2315 {
2316 mipPitch = Max(mipPitch >> 1, 1u);
2317 mipHeight = Max(mipHeight >> 1, 1u);
2318
2319 if (is3dThick || is3dThin)
2320 {
2321 mipDepth = Max(mipDepth >> 1, 1u);
2322 }
2323 }
2324 }
2325
2326 return endingMip;
2327 }
2328
2329 /**
2330 ****************************************************************************************************
2331 * Lib::GetMipStartPos
2332 *
2333 * @brief
2334 * Internal function to get out information about mip logical start position
2335 *
2336 * @return
2337 * logical start position in macro block width/heith/depth of one mip level within one slice
2338 ****************************************************************************************************
2339 */
2340 Dim3d Lib::GetMipStartPos(
2341 AddrResourceType resourceType,
2342 AddrSwizzleMode swizzleMode,
2343 UINT_32 width,
2344 UINT_32 height,
2345 UINT_32 depth,
2346 UINT_32 blockWidth,
2347 UINT_32 blockHeight,
2348 UINT_32 blockDepth,
2349 UINT_32 mipId,
2350 UINT_32* pMipTailOffset) const
2351 {
2352 Dim3d mipStartPos = {0};
2353
2354 const Dim3d tailMaxDim =
2355 GetMipTailDim(resourceType, swizzleMode, blockWidth, blockHeight, blockDepth);
2356
2357 // Report mip in tail if Mip0 is already in mip tail
2358 BOOL_32 inMipTail = IsInMipTail(resourceType, swizzleMode, tailMaxDim, width, height, depth);
2359
2360 UINT_32 log2blkSize = GetBlockSizeLog2(swizzleMode);
2361
2362 if (inMipTail == FALSE)
2363 {
2364 // Mip 0 dimension, unit in block
2365 UINT_32 mipWidthInBlk = width / blockWidth;
2366 UINT_32 mipHeightInBlk = height / blockHeight;
2367 UINT_32 mipDepthInBlk = depth / blockDepth;
2368 AddrMajorMode majorMode = GetMajorMode(resourceType,
2369 swizzleMode,
2370 mipWidthInBlk,
2371 mipHeightInBlk,
2372 mipDepthInBlk);
2373
2374 UINT_32 endingMip = mipId + 1;
2375
2376 for (UINT_32 i = 1; i <= mipId; i++)
2377 {
2378 if ((i == 1) || (i == 3))
2379 {
2380 if (majorMode == ADDR_MAJOR_Y)
2381 {
2382 mipStartPos.w += mipWidthInBlk;
2383 }
2384 else
2385 {
2386 mipStartPos.h += mipHeightInBlk;
2387 }
2388 }
2389 else
2390 {
2391 if (majorMode == ADDR_MAJOR_X)
2392 {
2393 mipStartPos.w += mipWidthInBlk;
2394 }
2395 else if (majorMode == ADDR_MAJOR_Y)
2396 {
2397 mipStartPos.h += mipHeightInBlk;
2398 }
2399 else
2400 {
2401 mipStartPos.d += mipDepthInBlk;
2402 }
2403 }
2404
2405 BOOL_32 inTail = FALSE;
2406
2407 if (IsThick(resourceType, swizzleMode))
2408 {
2409 UINT_32 dim = log2blkSize % 3;
2410
2411 if (dim == 0)
2412 {
2413 inTail =
2414 (mipWidthInBlk <= 2) && (mipHeightInBlk == 1) && (mipDepthInBlk <= 2);
2415 }
2416 else if (dim == 1)
2417 {
2418 inTail =
2419 (mipWidthInBlk == 1) && (mipHeightInBlk <= 2) && (mipDepthInBlk <= 2);
2420 }
2421 else
2422 {
2423 inTail =
2424 (mipWidthInBlk <= 2) && (mipHeightInBlk <= 2) && (mipDepthInBlk == 1);
2425 }
2426 }
2427 else
2428 {
2429 if (log2blkSize & 1)
2430 {
2431 inTail = (mipWidthInBlk <= 2) && (mipHeightInBlk == 1);
2432 }
2433 else
2434 {
2435 inTail = (mipWidthInBlk == 1) && (mipHeightInBlk <= 2);
2436 }
2437 }
2438
2439 if (inTail)
2440 {
2441 endingMip = i;
2442 break;
2443 }
2444
2445 mipWidthInBlk = RoundHalf(mipWidthInBlk);
2446 mipHeightInBlk = RoundHalf(mipHeightInBlk);
2447 mipDepthInBlk = RoundHalf(mipDepthInBlk);
2448 }
2449
2450 if (mipId >= endingMip)
2451 {
2452 inMipTail = TRUE;
2453 UINT_32 index = mipId - endingMip + MaxMacroBits - log2blkSize;
2454 ADDR_ASSERT(index < sizeof(MipTailOffset) / sizeof(UINT_32));
2455 *pMipTailOffset = MipTailOffset[index] << 8;
2456 }
2457 }
2458 else
2459 {
2460 UINT_32 index = mipId + MaxMacroBits - log2blkSize;
2461 ADDR_ASSERT(index < sizeof(MipTailOffset) / sizeof(UINT_32));
2462 *pMipTailOffset = MipTailOffset[index] << 8;
2463 }
2464
2465 return mipStartPos;
2466 }
2467
2468 /**
2469 ****************************************************************************************************
2470 * Lib::GetMipTailDim
2471 *
2472 * @brief
2473 * Internal function to get out max dimension of first level in mip tail
2474 *
2475 * @return
2476 * Max Width/Height/Depth value of the first mip fitted in mip tail
2477 ****************************************************************************************************
2478 */
2479 Dim3d Lib::GetMipTailDim(
2480 AddrResourceType resourceType,
2481 AddrSwizzleMode swizzleMode,
2482 UINT_32 blockWidth,
2483 UINT_32 blockHeight,
2484 UINT_32 blockDepth) const
2485 {
2486 Dim3d out = {blockWidth, blockHeight, blockDepth};
2487 UINT_32 log2blkSize = GetBlockSizeLog2(swizzleMode);
2488
2489 if (IsThick(resourceType, swizzleMode))
2490 {
2491 UINT_32 dim = log2blkSize % 3;
2492
2493 if (dim == 0)
2494 {
2495 out.h >>= 1;
2496 }
2497 else if (dim == 1)
2498 {
2499 out.w >>= 1;
2500 }
2501 else
2502 {
2503 out.d >>= 1;
2504 }
2505 }
2506 else
2507 {
2508 if (log2blkSize & 1)
2509 {
2510 out.h >>= 1;
2511 }
2512 else
2513 {
2514 out.w >>= 1;
2515 }
2516 }
2517
2518 return out;
2519 }
2520
2521 /**
2522 ****************************************************************************************************
2523 * Lib::ComputeSurface2DMicroBlockOffset
2524 *
2525 * @brief
2526 * Internal function to calculate micro block (256B) offset from coord for 2D resource
2527 *
2528 * @return
2529 * micro block (256B) offset for 2D resource
2530 ****************************************************************************************************
2531 */
2532 UINT_32 Lib::ComputeSurface2DMicroBlockOffset(
2533 const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
2534 {
2535 ADDR_ASSERT(IsThin(pIn->resourceType, pIn->swizzleMode));
2536
2537 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
2538 UINT_32 microBlockOffset = 0;
2539 if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
2540 {
2541 UINT_32 xBits = pIn->x << log2ElementBytes;
2542 microBlockOffset = (xBits & 0xf) | ((pIn->y & 0x3) << 4);
2543 if (log2ElementBytes < 3)
2544 {
2545 microBlockOffset |= (pIn->y & 0x4) << 4;
2546 if (log2ElementBytes == 0)
2547 {
2548 microBlockOffset |= (pIn->y & 0x8) << 4;
2549 }
2550 else
2551 {
2552 microBlockOffset |= (xBits & 0x10) << 3;
2553 }
2554 }
2555 else
2556 {
2557 microBlockOffset |= (xBits & 0x30) << 2;
2558 }
2559 }
2560 else if (IsDisplaySwizzle(pIn->resourceType, pIn->swizzleMode))
2561 {
2562 if (log2ElementBytes == 4)
2563 {
2564 microBlockOffset = (GetBit(pIn->x, 0) << 4) |
2565 (GetBit(pIn->y, 0) << 5) |
2566 (GetBit(pIn->x, 1) << 6) |
2567 (GetBit(pIn->y, 1) << 7);
2568 }
2569 else
2570 {
2571 microBlockOffset = GetBits(pIn->x, 0, 3, log2ElementBytes) |
2572 GetBits(pIn->y, 1, 2, 3 + log2ElementBytes) |
2573 GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
2574 GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
2575 microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
2576 (GetBit(pIn->y, 0) << 4) |
2577 GetBits(microBlockOffset, 4, 3, 5);
2578 }
2579 }
2580 else if (IsRotateSwizzle(pIn->swizzleMode))
2581 {
2582 microBlockOffset = GetBits(pIn->y, 0, 3, log2ElementBytes) |
2583 GetBits(pIn->x, 1, 2, 3 + log2ElementBytes) |
2584 GetBits(pIn->x, 3, 1, 5 + log2ElementBytes) |
2585 GetBits(pIn->y, 3, 1, 6 + log2ElementBytes);
2586 microBlockOffset = GetBits(microBlockOffset, 0, 4, 0) |
2587 (GetBit(pIn->x, 0) << 4) |
2588 GetBits(microBlockOffset, 4, 3, 5);
2589 if (log2ElementBytes == 3)
2590 {
2591 microBlockOffset = GetBits(microBlockOffset, 0, 6, 0) |
2592 GetBits(pIn->x, 1, 2, 6);
2593 }
2594 }
2595
2596 return microBlockOffset;
2597 }
2598
2599 /**
2600 ****************************************************************************************************
2601 * Lib::ComputeSurface3DMicroBlockOffset
2602 *
2603 * @brief
2604 * Internal function to calculate micro block (1KB) offset from coord for 3D resource
2605 *
2606 * @return
2607 * micro block (1KB) offset for 3D resource
2608 ****************************************************************************************************
2609 */
2610 UINT_32 Lib::ComputeSurface3DMicroBlockOffset(
2611 const _ADDR2_COMPUTE_SURFACE_ADDRFROMCOORD_INPUT* pIn) const
2612 {
2613 ADDR_ASSERT(IsThick(pIn->resourceType, pIn->swizzleMode));
2614
2615 UINT_32 log2ElementBytes = Log2(pIn->bpp >> 3);
2616 UINT_32 microBlockOffset = 0;
2617 if (IsStandardSwizzle(pIn->resourceType, pIn->swizzleMode))
2618 {
2619 if (log2ElementBytes == 0)
2620 {
2621 microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
2622 }
2623 else if (log2ElementBytes == 1)
2624 {
2625 microBlockOffset = ((pIn->slice & 4) >> 2) | ((pIn->y & 4) >> 1);
2626 }
2627 else if (log2ElementBytes == 2)
2628 {
2629 microBlockOffset = ((pIn->y & 4) >> 2) | ((pIn->x & 4) >> 1);
2630 }
2631 else if (log2ElementBytes == 3)
2632 {
2633 microBlockOffset = (pIn->x & 6) >> 1;
2634 }
2635 else
2636 {
2637 microBlockOffset = pIn->x & 3;
2638 }
2639
2640 microBlockOffset <<= 8;
2641
2642 UINT_32 xBits = pIn->x << log2ElementBytes;
2643 microBlockOffset |= (xBits & 0xf) | ((pIn->y & 0x3) << 4) | ((pIn->slice & 0x3) << 6);
2644 }
2645 else if (IsZOrderSwizzle(pIn->swizzleMode))
2646 {
2647 UINT_32 xh, yh, zh;
2648
2649 if (log2ElementBytes == 0)
2650 {
2651 microBlockOffset =
2652 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
2653 microBlockOffset = microBlockOffset | ((pIn->slice & 3) << 4) | ((pIn->x & 4) << 4);
2654
2655 xh = pIn->x >> 3;
2656 yh = pIn->y >> 2;
2657 zh = pIn->slice >> 2;
2658 }
2659 else if (log2ElementBytes == 1)
2660 {
2661 microBlockOffset =
2662 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->y & 2) << 2);
2663 microBlockOffset = (microBlockOffset << 1) | ((pIn->slice & 3) << 5);
2664
2665 xh = pIn->x >> 2;
2666 yh = pIn->y >> 2;
2667 zh = pIn->slice >> 2;
2668 }
2669 else if (log2ElementBytes == 2)
2670 {
2671 microBlockOffset =
2672 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->x & 2) << 1) | ((pIn->slice & 1) << 3);
2673 microBlockOffset = (microBlockOffset << 2) | ((pIn->y & 2) << 5);
2674
2675 xh = pIn->x >> 2;
2676 yh = pIn->y >> 2;
2677 zh = pIn->slice >> 1;
2678 }
2679 else if (log2ElementBytes == 3)
2680 {
2681 microBlockOffset =
2682 (pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2) | ((pIn->x & 2) << 2);
2683 microBlockOffset <<= 3;
2684
2685 xh = pIn->x >> 2;
2686 yh = pIn->y >> 1;
2687 zh = pIn->slice >> 1;
2688 }
2689 else
2690 {
2691 microBlockOffset =
2692 (((pIn->x & 1) | ((pIn->y & 1) << 1) | ((pIn->slice & 1) << 2)) << 4);
2693
2694 xh = pIn->x >> 1;
2695 yh = pIn->y >> 1;
2696 zh = pIn->slice >> 1;
2697 }
2698
2699 microBlockOffset |= ((MortonGen3d(xh, yh, zh, 1) << 7) & 0x380);
2700 }
2701
2702 return microBlockOffset;
2703 }
2704
2705 /**
2706 ****************************************************************************************************
2707 * Lib::GetPipeXorBits
2708 *
2709 * @brief
2710 * Internal function to get bits number for pipe/se xor operation
2711 *
2712 * @return
2713 * ADDR_E_RETURNCODE
2714 ****************************************************************************************************
2715 */
2716 UINT_32 Lib::GetPipeXorBits(
2717 UINT_32 macroBlockBits) const
2718 {
2719 ADDR_ASSERT(macroBlockBits >= m_pipeInterleaveLog2);
2720
2721 // Total available xor bits
2722 UINT_32 xorBits = macroBlockBits - m_pipeInterleaveLog2;
2723
2724 // Pipe/Se xor bits
2725 UINT_32 pipeBits = Min(xorBits, m_pipesLog2 + m_seLog2);
2726
2727 return pipeBits;
2728 }
2729
2730 /**
2731 ****************************************************************************************************
2732 * Lib::GetBankXorBits
2733 *
2734 * @brief
2735 * Internal function to get bits number for pipe/se xor operation
2736 *
2737 * @return
2738 * ADDR_E_RETURNCODE
2739 ****************************************************************************************************
2740 */
2741 UINT_32 Lib::GetBankXorBits(
2742 UINT_32 macroBlockBits) const
2743 {
2744 UINT_32 pipeBits = GetPipeXorBits(macroBlockBits);
2745
2746 // Bank xor bits
2747 UINT_32 bankBits = Min(macroBlockBits - pipeBits - m_pipeInterleaveLog2, m_banksLog2);
2748
2749 return bankBits;
2750 }
2751
2752 /**
2753 ****************************************************************************************************
2754 * Lib::Addr2GetPreferredSurfaceSetting
2755 *
2756 * @brief
2757 * Internal function to get suggested surface information for cliet to use
2758 *
2759 * @return
2760 * ADDR_E_RETURNCODE
2761 ****************************************************************************************************
2762 */
2763 ADDR_E_RETURNCODE Lib::Addr2GetPreferredSurfaceSetting(
2764 const ADDR2_GET_PREFERRED_SURF_SETTING_INPUT* pIn,
2765 ADDR2_GET_PREFERRED_SURF_SETTING_OUTPUT* pOut) const
2766 {
2767 // Macro define resource block type
2768 enum AddrBlockType
2769 {
2770 AddrBlockMicro = 0, // Resource uses 256B block
2771 AddrBlock4KB = 1, // Resource uses 4KB block
2772 AddrBlock64KB = 2, // Resource uses 64KB block
2773 AddrBlockVar = 3, // Resource uses var blcok
2774 AddrBlockLinear = 4, // Resource uses linear swizzle mode
2775
2776 AddrBlockMaxTiledType = AddrBlock64KB + 1,
2777 };
2778
2779 enum AddrBlockSet
2780 {
2781 AddrBlockSetMicro = 1 << AddrBlockMicro,
2782 AddrBlockSetMacro4KB = 1 << AddrBlock4KB,
2783 AddrBlockSetMacro64KB = 1 << AddrBlock64KB,
2784 AddrBlockSetVar = 1 << AddrBlockVar,
2785 AddrBlockSetLinear = 1 << AddrBlockLinear,
2786
2787 AddrBlockSetMacro = AddrBlockSetMacro4KB | AddrBlockSetMacro64KB,
2788 };
2789
2790 ADDR_E_RETURNCODE returnCode = ADDR_OK;
2791 ElemLib* pElemLib = GetElemLib();
2792
2793 // Set format to INVALID will skip this conversion
2794 UINT_32 expandX = 1;
2795 UINT_32 expandY = 1;
2796 UINT_32 bpp = pIn->bpp;
2797 if (pIn->format != ADDR_FMT_INVALID)
2798 {
2799 // Don't care for this case
2800 ElemMode elemMode = ADDR_UNCOMPRESSED;
2801
2802 // Get compression/expansion factors and element mode which indicates compression/expansion
2803 bpp = pElemLib->GetBitsPerPixel(pIn->format,
2804 &elemMode,
2805 &expandX,
2806 &expandY);
2807 }
2808
2809 UINT_32 numSamples = Max(pIn->numSamples, 1u);
2810 UINT_32 numFrags = (pIn->numFrags == 0) ? numSamples : pIn->numFrags;
2811 UINT_32 width = Max(pIn->width / expandX, 1u);
2812 UINT_32 height = Max(pIn->height / expandY, 1u);
2813 UINT_32 slice = Max(pIn->numSlices, 1u);
2814 UINT_32 numMipLevels = Max(pIn->numMipLevels, 1u);
2815
2816 if (pIn->flags.fmask)
2817 {
2818 bpp = GetFmaskBpp(numSamples, numFrags);
2819 numFrags = 1;
2820 numSamples = 1;
2821 pOut->resourceType = ADDR_RSRC_TEX_2D;
2822 }
2823 else
2824 {
2825 // The output may get changed for volume(3D) texture resource in future
2826 pOut->resourceType = pIn->resourceType;
2827 }
2828
2829 if (IsTex1d(pOut->resourceType))
2830 {
2831 pOut->swizzleMode = ADDR_SW_LINEAR;
2832 pOut->validBlockSet.value = AddrBlockSetLinear;
2833 pOut->canXor = FALSE;
2834 }
2835 else
2836 {
2837 ADDR2_BLOCK_SET blockSet;
2838 AddrSwType swType;
2839
2840 blockSet.value = 0;
2841
2842 BOOL_32 tryPrtXor = pIn->flags.prt;
2843
2844 // Filter out improper swType and blockSet by HW restriction
2845 if (pIn->flags.fmask || pIn->flags.depth || pIn->flags.stencil)
2846 {
2847 ADDR_ASSERT(IsTex2d(pOut->resourceType));
2848 blockSet.value = AddrBlockSetMacro;
2849 swType = ADDR_SW_Z;
2850 }
2851 else if (pElemLib->IsBlockCompressed(pIn->format))
2852 {
2853 // block compressed formats (BCx, ASTC, ETC2) must be either S or D modes. Not sure
2854 // under what circumstances "_D" would be appropriate as these formats are not
2855 // displayable.
2856 blockSet.value = AddrBlockSetMacro;
2857 swType = ADDR_SW_S;
2858 }
2859 else if (IsTex3d(pOut->resourceType))
2860 {
2861 blockSet.value = AddrBlockSetLinear | AddrBlockSetMacro;
2862 swType = (slice >= 8) ? ADDR_SW_Z : ADDR_SW_S;
2863 }
2864 else if (numMipLevels > 1)
2865 {
2866 ADDR_ASSERT(numFrags == 1);
2867 blockSet.value = AddrBlockSetLinear | AddrBlockSetMacro;
2868 swType = pIn->flags.display ? ADDR_SW_D : ADDR_SW_S;
2869 }
2870 else if ((numFrags > 1) || (numSamples > 1))
2871 {
2872 ADDR_ASSERT(IsTex2d(pOut->resourceType));
2873 blockSet.value = AddrBlockSetMacro;
2874 swType = pIn->flags.display ? ADDR_SW_D : ADDR_SW_S;
2875 }
2876 else
2877 {
2878 ADDR_ASSERT(IsTex2d(pOut->resourceType));
2879 blockSet.value = AddrBlockSetLinear | AddrBlockSetMicro | AddrBlockSetMacro;
2880 if (pIn->flags.rotated || pIn->flags.display)
2881 {
2882 swType = pIn->flags.rotated ? ADDR_SW_R : ADDR_SW_D;
2883
2884 if (IsDce12())
2885 {
2886 if (pIn->bpp != 32)
2887 {
2888 blockSet.micro = FALSE;
2889 }
2890
2891 // DCE12 does not support display surface to be _T swizzle mode
2892 tryPrtXor = FALSE;
2893 }
2894 else
2895 {
2896 ADDR_NOT_IMPLEMENTED();
2897 }
2898 }
2899 else if (pIn->flags.overlay)
2900 {
2901 swType = ADDR_SW_D;
2902 }
2903 else
2904 {
2905 swType = ADDR_SW_S;
2906 }
2907 }
2908
2909 if ((numFrags > 1) &&
2910 (GetBlockSize(ADDR_SW_4KB) < (m_pipeInterleaveBytes * numFrags)))
2911 {
2912 // MSAA surface must have blk_bytes/pipe_interleave >= num_samples
2913 blockSet.macro4KB = FALSE;
2914 }
2915
2916 if (pIn->flags.prt)
2917 {
2918 blockSet.value &= AddrBlock64KB;
2919 }
2920
2921 // Apply customized forbidden setting
2922 blockSet.value &= ~pIn->forbiddenBlock.value;
2923
2924 if (pIn->maxAlign > 0)
2925 {
2926 if (pIn->maxAlign < GetBlockSize(ADDR_SW_64KB))
2927 {
2928 blockSet.macro64KB = FALSE;
2929 }
2930
2931 if (pIn->maxAlign < GetBlockSize(ADDR_SW_4KB))
2932 {
2933 blockSet.macro4KB = FALSE;
2934 }
2935
2936 if (pIn->maxAlign < GetBlockSize(ADDR_SW_256B))
2937 {
2938 blockSet.micro = FALSE;
2939 }
2940 }
2941
2942 Dim3d blkDim[AddrBlockMaxTiledType] = {{0}, {0}, {0}};
2943 Dim3d padDim[AddrBlockMaxTiledType] = {{0}, {0}, {0}};
2944 UINT_64 padSize[AddrBlockMaxTiledType] = {0};
2945
2946 if (blockSet.micro)
2947 {
2948 returnCode = ComputeBlockDimensionForSurf(&blkDim[AddrBlockMicro],
2949 bpp,
2950 numFrags,
2951 pOut->resourceType,
2952 ADDR_SW_256B);
2953
2954 if (returnCode == ADDR_OK)
2955 {
2956 if ((blkDim[AddrBlockMicro].w >= width) && (blkDim[AddrBlockMicro].h >= height))
2957 {
2958 // If one 256B block can contain the surface, don't bother bigger block type
2959 blockSet.macro4KB = FALSE;
2960 blockSet.macro64KB = FALSE;
2961 blockSet.var = FALSE;
2962 }
2963
2964 padSize[AddrBlockMicro] = ComputePadSize(&blkDim[AddrBlockMicro], width, height,
2965 slice, &padDim[AddrBlockMicro]);
2966 }
2967 }
2968
2969 if ((returnCode == ADDR_OK) && (blockSet.macro4KB))
2970 {
2971 returnCode = ComputeBlockDimensionForSurf(&blkDim[AddrBlock4KB],
2972 bpp,
2973 numFrags,
2974 pOut->resourceType,
2975 ADDR_SW_4KB);
2976
2977 if (returnCode == ADDR_OK)
2978 {
2979 padSize[AddrBlock4KB] = ComputePadSize(&blkDim[AddrBlock4KB], width, height,
2980 slice, &padDim[AddrBlock4KB]);
2981
2982 ADDR_ASSERT(padSize[AddrBlock4KB] >= padSize[AddrBlockMicro]);
2983 }
2984 }
2985
2986 if ((returnCode == ADDR_OK) && (blockSet.macro64KB))
2987 {
2988 returnCode = ComputeBlockDimensionForSurf(&blkDim[AddrBlock64KB],
2989 bpp,
2990 numFrags,
2991 pOut->resourceType,
2992 ADDR_SW_64KB);
2993
2994 if (returnCode == ADDR_OK)
2995 {
2996 padSize[AddrBlock64KB] = ComputePadSize(&blkDim[AddrBlock64KB], width, height,
2997 slice, &padDim[AddrBlock64KB]);
2998
2999 ADDR_ASSERT(padSize[AddrBlock64KB] >= padSize[AddrBlock4KB]);
3000 ADDR_ASSERT(padSize[AddrBlock64KB] >= padSize[AddrBlockMicro]);
3001
3002 if ((padSize[AddrBlock64KB] >= static_cast<UINT_64>(width) * height * slice * 2) &&
3003 ((blockSet.value & ~AddrBlockSetMacro64KB) != 0))
3004 {
3005 // If 64KB block waste more than half memory on padding, filter it out from
3006 // candidate list when it is not the only choice left
3007 blockSet.macro64KB = FALSE;
3008 }
3009 }
3010 }
3011
3012 if (returnCode == ADDR_OK)
3013 {
3014 // Use minimum block type which meets all conditions above if flag minimizeAlign was set
3015 if (pIn->flags.minimizeAlign)
3016 {
3017 // If padded size of 64KB block is larger than padded size of 256B block or 4KB
3018 // block, filter out 64KB block from candidate list
3019 if (blockSet.macro64KB &&
3020 ((blockSet.micro && (padSize[AddrBlockMicro] < padSize[AddrBlock64KB])) ||
3021 (blockSet.macro4KB && (padSize[AddrBlock4KB] < padSize[AddrBlock64KB]))))
3022 {
3023 blockSet.macro64KB = FALSE;
3024 }
3025
3026 // If padded size of 4KB block is larger than padded size of 256B block,
3027 // filter out 4KB block from candidate list
3028 if (blockSet.macro4KB &&
3029 blockSet.micro &&
3030 (padSize[AddrBlockMicro] < padSize[AddrBlock4KB]))
3031 {
3032 blockSet.macro4KB = FALSE;
3033 }
3034 }
3035 // Filter out 64KB/4KB block if a smaller block type has 2/3 or less memory footprint
3036 else if (pIn->flags.opt4space)
3037 {
3038 UINT_64 threshold =
3039 blockSet.micro ?
3040 padSize[AddrBlockMicro] :
3041 (blockSet.macro4KB ? padSize[AddrBlock4KB] : padSize[AddrBlock64KB]);
3042
3043 threshold += threshold >> 1;
3044
3045 if (blockSet.macro64KB && (padSize[AddrBlock64KB] > threshold))
3046 {
3047 blockSet.macro64KB = FALSE;
3048 }
3049
3050 if (blockSet.macro4KB && (padSize[AddrBlock4KB] > threshold))
3051 {
3052 blockSet.macro4KB = FALSE;
3053 }
3054 }
3055
3056 if (blockSet.value == 0)
3057 {
3058 // Bad things happen, client will not get any useful information from AddrLib.
3059 // Maybe we should fill in some output earlier instead of outputing nothing?
3060 ADDR_ASSERT_ALWAYS();
3061 returnCode = ADDR_INVALIDPARAMS;
3062 }
3063 else
3064 {
3065 pOut->validBlockSet = blockSet;
3066 pOut->canXor = (pIn->flags.prt == FALSE) &&
3067 (blockSet.macro4KB || blockSet.macro64KB || blockSet.var);
3068
3069 if (blockSet.macro64KB || blockSet.macro4KB)
3070 {
3071 if (swType == ADDR_SW_Z)
3072 {
3073 pOut->swizzleMode = blockSet.macro64KB ? ADDR_SW_64KB_Z : ADDR_SW_4KB_Z;
3074 }
3075 else if (swType == ADDR_SW_S)
3076 {
3077 pOut->swizzleMode = blockSet.macro64KB ? ADDR_SW_64KB_S : ADDR_SW_4KB_S;
3078 }
3079 else if (swType == ADDR_SW_D)
3080 {
3081 pOut->swizzleMode = blockSet.macro64KB ? ADDR_SW_64KB_D : ADDR_SW_4KB_D;
3082 }
3083 else
3084 {
3085 ADDR_ASSERT(swType == ADDR_SW_R);
3086 pOut->swizzleMode = blockSet.macro64KB ? ADDR_SW_64KB_R : ADDR_SW_4KB_R;
3087 }
3088
3089 if (pIn->noXor == FALSE)
3090 {
3091 if (tryPrtXor && blockSet.macro64KB)
3092 {
3093 // Client wants PRTXOR, give back _T swizzle mode if 64KB is available
3094 static const UINT_32 PrtGap = ADDR_SW_64KB_Z_T - ADDR_SW_64KB_Z;
3095 pOut->swizzleMode =
3096 static_cast<AddrSwizzleMode>(pOut->swizzleMode + PrtGap);
3097 }
3098 else if (pOut->canXor)
3099 {
3100 // Client wants XOR and this is allowed, return XOR version swizzle mode
3101 static const UINT_32 XorGap = ADDR_SW_4KB_Z_X - ADDR_SW_4KB_Z;
3102 pOut->swizzleMode =
3103 static_cast<AddrSwizzleMode>(pOut->swizzleMode + XorGap);
3104 }
3105 }
3106 }
3107 else if (blockSet.var)
3108 {
3109 // Designer consider this swizzle is usless for most cases
3110 ADDR_UNHANDLED_CASE();
3111 }
3112 else if (blockSet.micro)
3113 {
3114 if (swType == ADDR_SW_S)
3115 {
3116 pOut->swizzleMode = ADDR_SW_256B_S;
3117 }
3118 else if (swType == ADDR_SW_D)
3119 {
3120 pOut->swizzleMode = ADDR_SW_256B_D;
3121 }
3122 else
3123 {
3124 ADDR_ASSERT(swType == ADDR_SW_R);
3125 pOut->swizzleMode = ADDR_SW_256B_R;
3126 }
3127 }
3128 else
3129 {
3130 ADDR_ASSERT(blockSet.linear);
3131 // Fall into this branch doesn't mean linear is suitable, only no other choices!
3132 pOut->swizzleMode = ADDR_SW_LINEAR;
3133 }
3134
3135 #if DEBUG
3136 // Post sanity check, at least AddrLib should accept the output generated by its own
3137 if (pOut->swizzleMode != ADDR_SW_LINEAR)
3138 {
3139 ADDR2_COMPUTE_SURFACE_INFO_INPUT localIn = {0};
3140 localIn.flags = pIn->flags;
3141 localIn.swizzleMode = pOut->swizzleMode;
3142 localIn.resourceType = pOut->resourceType;
3143 localIn.format = pIn->format;
3144 localIn.bpp = bpp;
3145 localIn.width = width;
3146 localIn.height = height;
3147 localIn.numSlices = slice;
3148 localIn.numMipLevels = numMipLevels;
3149 localIn.numSamples = numSamples;
3150 localIn.numFrags = numFrags;
3151
3152 ADDR_E_RETURNCODE coherentCheck = ComputeSurfaceInfoSanityCheck(&localIn);
3153 ADDR_ASSERT(coherentCheck == ADDR_OK);
3154
3155 // TODO : check all valid block type available in validBlockSet?
3156 }
3157 #endif
3158 }
3159 }
3160 }
3161
3162 return returnCode;
3163 }
3164
3165 /**
3166 ****************************************************************************************************
3167 * Lib::ComputeBlock256Equation
3168 *
3169 * @brief
3170 * Compute equation for block 256B
3171 *
3172 * @return
3173 * If equation computed successfully
3174 *
3175 ****************************************************************************************************
3176 */
3177 ADDR_E_RETURNCODE Lib::ComputeBlock256Equation(
3178 AddrResourceType rsrcType,
3179 AddrSwizzleMode swMode,
3180 UINT_32 elementBytesLog2,
3181 ADDR_EQUATION* pEquation) const
3182 {
3183 ADDR_E_RETURNCODE ret;
3184
3185 if (IsBlock256b(swMode))
3186 {
3187 ret = HwlComputeBlock256Equation(rsrcType, swMode, elementBytesLog2, pEquation);
3188 }
3189 else
3190 {
3191 ADDR_ASSERT_ALWAYS();
3192 ret = ADDR_INVALIDPARAMS;
3193 }
3194
3195 return ret;
3196 }
3197
3198 /**
3199 ****************************************************************************************************
3200 * Lib::ComputeThinEquation
3201 *
3202 * @brief
3203 * Compute equation for 2D/3D resource which use THIN mode
3204 *
3205 * @return
3206 * If equation computed successfully
3207 *
3208 ****************************************************************************************************
3209 */
3210 ADDR_E_RETURNCODE Lib::ComputeThinEquation(
3211 AddrResourceType rsrcType,
3212 AddrSwizzleMode swMode,
3213 UINT_32 elementBytesLog2,
3214 ADDR_EQUATION* pEquation) const
3215 {
3216 ADDR_E_RETURNCODE ret;
3217
3218 if (IsThin(rsrcType, swMode))
3219 {
3220 ret = HwlComputeThinEquation(rsrcType, swMode, elementBytesLog2, pEquation);
3221 }
3222 else
3223 {
3224 ADDR_ASSERT_ALWAYS();
3225 ret = ADDR_INVALIDPARAMS;
3226 }
3227
3228 return ret;
3229 }
3230
3231 /**
3232 ****************************************************************************************************
3233 * Lib::ComputeThickEquation
3234 *
3235 * @brief
3236 * Compute equation for 3D resource which use THICK mode
3237 *
3238 * @return
3239 * If equation computed successfully
3240 *
3241 ****************************************************************************************************
3242 */
3243 ADDR_E_RETURNCODE Lib::ComputeThickEquation(
3244 AddrResourceType rsrcType,
3245 AddrSwizzleMode swMode,
3246 UINT_32 elementBytesLog2,
3247 ADDR_EQUATION* pEquation) const
3248 {
3249 ADDR_E_RETURNCODE ret;
3250
3251 if (IsThick(rsrcType, swMode))
3252 {
3253 ret = HwlComputeThickEquation(rsrcType, swMode, elementBytesLog2, pEquation);
3254 }
3255 else
3256 {
3257 ADDR_ASSERT_ALWAYS();
3258 ret = ADDR_INVALIDPARAMS;
3259 }
3260
3261 return ret;
3262 }
3263
3264 } // V2
3265 } // Addr
3266