1 /*==============================================================================
2 Copyright(c) 2017 Intel Corporation
3
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files(the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and / or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 ============================================================================*/
22
23 #include "Internal/Common/GmmLibInc.h"
24 #include "Internal/Common/Texture/GmmGen10TextureCalc.h"
25 #include "Internal/Common/Texture/GmmGen11TextureCalc.h"
26
27 /////////////////////////////////////////////////////////////////////////////////////
28 /// This function calculates the (X,Y) address of each given plane. X is in bytes
29 /// and Y is in scanlines.
30 ///
31 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO
32 ///
33 /////////////////////////////////////////////////////////////////////////////////////
FillPlanarOffsetAddress(GMM_TEXTURE_INFO * pTexInfo)34 void GmmLib::GmmGen11TextureCalc::FillPlanarOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
35 {
36 GMM_GFX_SIZE_T *pUOffsetX, *pUOffsetY;
37 GMM_GFX_SIZE_T *pVOffsetX, *pVOffsetY;
38 uint32_t YHeight = 0, VHeight = 0;
39 bool UVPacked = false;
40 uint32_t Height;
41 uint32_t WidthBytesPhysical = GFX_ULONG_CAST(pTexInfo->BaseWidth) * pTexInfo->BitsPerPixel >> 3;
42
43 #define SWAP_UV() \
44 { \
45 GMM_GFX_SIZE_T *pTemp; \
46 \
47 pTemp = pUOffsetX; \
48 pUOffsetX = pVOffsetX; \
49 pVOffsetX = pTemp; \
50 \
51 pTemp = pUOffsetY; \
52 pUOffsetY = pVOffsetY; \
53 pVOffsetY = pTemp; \
54 }
55
56 __GMM_ASSERTPTR(pTexInfo, VOIDRETURN);
57 __GMM_ASSERTPTR(((pTexInfo->TileMode < GMM_TILE_MODES) && (pTexInfo->TileMode >= TILE_NONE)), VOIDRETURN);
58 GMM_DPF_ENTER;
59
60 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
61
62 // GMM_PLANE_Y always at (0, 0)...
63 pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
64 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
65
66 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = 0;
67 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = 0;
68
69 Height = pTexInfo->BaseHeight;
70 if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
71 {
72 Height = __GMM_EXPAND_HEIGHT(this, Height, pTexInfo->Alignment.VAlign, pTexInfo);
73 Height = ScaleTextureHeight(pTexInfo, Height);
74 if(pTexInfo->Flags.Gpu.UnifiedAuxSurface)
75 {
76 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
77 }
78 }
79
80 // GMM_PLANE_U/V Planes...
81 pUOffsetX = &pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U];
82 pUOffsetY = &pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U];
83 pVOffsetX = &pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V];
84 pVOffsetY = &pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V];
85
86 switch(pTexInfo->Format)
87 {
88 case GMM_FORMAT_IMC1:
89 SWAP_UV(); // IMC1 = IMC3 with Swapped U/V
90 case GMM_FORMAT_IMC3:
91 case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
92 // YYYYYYYY
93 // YYYYYYYY
94 // YYYYYYYY
95 // YYYYYYYY
96 // UUUU
97 // UUUU
98 // VVVV
99 // VVVV
100 case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
101 // YYYYYYYY
102 // YYYYYYYY
103 // YYYYYYYY
104 // YYYYYYYY
105 // UUUUUUUU
106 // UUUUUUUU
107 // VVVVVVVV
108 // VVVVVVVV
109 {
110 *pUOffsetX = 0;
111 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
112 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
113
114 *pVOffsetX = 0;
115 VHeight = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
116 *pVOffsetY =
117 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
118 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
119
120 break;
121 }
122 case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
123 //YYYYYYYY
124 //YYYYYYYY
125 //YYYYYYYY
126 //YYYYYYYY
127 //UUUUUUUU
128 //VVVVVVVV
129 {
130 *pUOffsetX = 0;
131 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
132 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
133
134 *pVOffsetX = 0;
135 VHeight = GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
136 *pVOffsetY =
137 GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) +
138 GFX_ALIGN(GFX_CEIL_DIV(pTexInfo->BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
139
140 break;
141 }
142 case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
143 // YYYYYYYY
144 // YYYYYYYY
145 // YYYYYYYY
146 // YYYYYYYY
147 // UU
148 // UU
149 // UU
150 // UU
151 // VV
152 // VV
153 // VV
154 // VV
155 case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
156 // YYYYYYYY
157 // YYYYYYYY
158 // YYYYYYYY
159 // YYYYYYYY
160 // UUUU
161 // UUUU
162 // UUUU
163 // UUUU
164 // VVVV
165 // VVVV
166 // VVVV
167 // VVVV
168 case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
169 // YYYYYYYY
170 // YYYYYYYY
171 // YYYYYYYY
172 // YYYYYYYY
173 // UUUUUUUU
174 // UUUUUUUU
175 // UUUUUUUU
176 // UUUUUUUU
177 // VVVVVVVV
178 // VVVVVVVV
179 // VVVVVVVV
180 // VVVVVVVV
181 {
182 *pUOffsetX = 0;
183 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
184 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
185
186 *pVOffsetX = 0;
187 VHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
188 *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
189
190 break;
191 }
192 case GMM_FORMAT_BGRP:
193 case GMM_FORMAT_RGBP:
194 {
195 //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
196 if(pTexInfo->Flags.Info.Linear)
197 {
198 *pUOffsetX = 0;
199 YHeight = pTexInfo->BaseHeight;
200 *pUOffsetY = pTexInfo->BaseHeight;
201
202 *pVOffsetX = 0;
203 VHeight = pTexInfo->BaseHeight;
204 *pVOffsetY = (GMM_GFX_SIZE_T)pTexInfo->BaseHeight * 2;
205 }
206 else //Tiled
207 {
208 *pUOffsetX = 0;
209 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
210 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
211
212 *pVOffsetX = 0;
213 VHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
214 *pVOffsetY = (GMM_GFX_SIZE_T)GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT) * 2;
215 }
216 break;
217 }
218 case GMM_FORMAT_IMC2:
219 SWAP_UV(); // IMC2 = IMC4 with Swapped U/V
220 case GMM_FORMAT_IMC4:
221 {
222 // YYYYYYYY
223 // YYYYYYYY
224 // YYYYYYYY
225 // YYYYYYYY
226 // UUUUVVVV
227 // UUUUVVVV
228
229 __GMM_ASSERT((pTexInfo->Pitch & 1) == 0);
230
231 *pUOffsetX = 0;
232 YHeight = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
233 *pUOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
234
235 *pVOffsetX = pTexInfo->Pitch / 2;
236 VHeight = GFX_CEIL_DIV(YHeight, 2);
237 *pVOffsetY = GFX_ALIGN(pTexInfo->BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
238
239 // Not technically UV packed but sizing works out the same
240 UVPacked = true;
241
242 break;
243 }
244 case GMM_FORMAT_I420: // I420 = IYUV
245 case GMM_FORMAT_IYUV:
246 SWAP_UV(); // I420/IYUV = YV12 with Swapped U/V
247 case GMM_FORMAT_YV12:
248 case GMM_FORMAT_YVU9:
249 {
250 // YYYYYYYY
251 // YYYYYYYY
252 // YYYYYYYY
253 // YYYYYYYY
254 // VVVVVV.. <-- V and U planes follow the Y plane, as linear
255 // ..UUUUUU arrays--without respect to pitch.
256
257 uint32_t YSize, YVSizeRShift, VSize, UOffset;
258 uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
259
260 YSize = GFX_ULONG_CAST(pTexInfo->Pitch) * pTexInfo->BaseHeight;
261
262 // YVU9 has one U/V pixel for each 4x4 Y block.
263 // The others have one U/V pixel for each 2x2 Y block.
264
265 // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
266 // The others have a ratio of 4 (2x2 --> 1).
267 YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
268
269 // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
270 // extra/unaligned Y pixels still need corresponding U/V pixels--So
271 // for the purpose of computing the UVSize, we must consider a
272 // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
273 // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
274 YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
275 YSizeForUVPurposes =
276 GFX_ALIGN(GFX_ULONG_CAST(pTexInfo->Pitch), YSizeForUVPurposesDimensionalAlignment) *
277 GFX_ALIGN(pTexInfo->BaseHeight, YSizeForUVPurposesDimensionalAlignment);
278
279 VSize = (YSizeForUVPurposes >> YVSizeRShift);
280 UOffset = YSize + VSize;
281
282 *pVOffsetX = 0;
283 *pVOffsetY = pTexInfo->BaseHeight;
284
285 *pUOffsetX = UOffset % pTexInfo->Pitch;
286 *pUOffsetY = UOffset / pTexInfo->Pitch;
287
288 YHeight = GFX_CEIL_DIV(YSize + 2 * VSize, WidthBytesPhysical);
289
290 break;
291 }
292 case GMM_FORMAT_NV12:
293 case GMM_FORMAT_NV21:
294 case GMM_FORMAT_NV11:
295 case GMM_FORMAT_P010:
296 case GMM_FORMAT_P012:
297 case GMM_FORMAT_P016:
298 case GMM_FORMAT_P208:
299 case GMM_FORMAT_P216:
300 {
301 // YYYYYYYY
302 // YYYYYYYY
303 // YYYYYYYY
304 // YYYYYYYY
305 // [UV-Packing]
306 *pUOffsetX = *pVOffsetX = 0;
307 YHeight = GFX_ALIGN(Height, __GMM_EVEN_ROW);
308 *pUOffsetY = *pVOffsetY = YHeight;
309
310 if((pTexInfo->Format == GMM_FORMAT_NV12) ||
311 (pTexInfo->Format == GMM_FORMAT_NV21) ||
312 (pTexInfo->Format == GMM_FORMAT_P010) ||
313 (pTexInfo->Format == GMM_FORMAT_P012) ||
314 (pTexInfo->Format == GMM_FORMAT_P016))
315 {
316 VHeight = GFX_CEIL_DIV(Height, 2);
317 }
318 else
319 {
320 VHeight = YHeight; // U/V plane is same as Y
321 }
322
323 UVPacked = true;
324 break;
325 }
326 default:
327 {
328 GMM_ASSERTDPF(0, "Unknown Video Format U\n");
329 break;
330 }
331 }
332
333 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_Y] = YHeight;
334 if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 2)
335 {
336 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] = VHeight;
337 }
338 else if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 3)
339 {
340 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_U] =
341 pTexInfo->OffsetInfo.Plane.UnAligned.Height[GMM_PLANE_V] = VHeight;
342 }
343
344 if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) || pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
345 {
346 GMM_GFX_SIZE_T TileHeight = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
347 GMM_GFX_SIZE_T TileWidth = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
348 GMM_GFX_SIZE_T PhysicalTileHeight = TileHeight;
349 if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) > IGFX_GEN11LP_CORE)
350 {
351 if(pTexInfo->Flags.Gpu.CCS && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS)
352 {
353 //U/V must be aligned to AuxT granularity, 4x pitchalign enforces 16K-align for 4KB tile,
354 //add extra padding for 64K AuxT, 1MB AuxT
355 if(GMM_IS_64KB_TILE(pTexInfo->Flags))
356 {
357 TileHeight *= (!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext)) ? 16 : 1; // For 64Kb Tile mode: Multiply TileHeight by 16 for 1 MB alignment
358 }
359 else
360 {
361 PhysicalTileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 1); // for 1 MB AuxT granularity, we do 1 MB alignment only in VA space and not in physical space, so do not multiply PhysicalTileHeight with 64 here
362 TileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 64); // For 4k Tile: Multiply TileHeight by 4 and Pitch by 4 for 64kb alignment, multiply TileHeight by 64 and Pitch by 4 for 1 MB alignment
363 }
364 }
365 }
366
367 *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
368 *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
369 *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
370 *pVOffsetY = UVPacked ?
371 GFX_ALIGN(*pVOffsetY, TileHeight) :
372 GFX_ALIGN(YHeight, TileHeight) + GFX_ALIGN(VHeight, TileHeight);
373
374 if(pTexInfo->Flags.Gpu.UnifiedAuxSurface && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
375 {
376 *pUOffsetY += pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y];
377 *pVOffsetY = *pUOffsetY;
378 }
379
380 // This is needed for FtrDisplayPageTables
381 if(pGmmLibContext->GetSkuTable().FtrDisplayPageTables)
382 {
383 pTexInfo->OffsetInfo.Plane.Aligned.Height[GMM_PLANE_Y] = GFX_ALIGN(YHeight, TileHeight);
384 if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 2)
385 {
386 pTexInfo->OffsetInfo.Plane.Aligned.Height[GMM_PLANE_U] = GFX_ALIGN(VHeight, TileHeight);
387 }
388 else if(pTexInfo->OffsetInfo.Plane.NoOfPlanes == 3)
389 {
390 pTexInfo->OffsetInfo.Plane.Aligned.Height[GMM_PLANE_U] =
391 pTexInfo->OffsetInfo.Plane.Aligned.Height[GMM_PLANE_V] = GFX_ALIGN(VHeight, TileHeight);
392 }
393 }
394 }
395
396 //Special case LKF MMC compressed surfaces
397 if(pTexInfo->Flags.Gpu.MMC &&
398 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
399 pTexInfo->Flags.Info.TiledY)
400 {
401 GMM_GFX_SIZE_T TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
402 GMM_GFX_SIZE_T TileWidth = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
403
404 *pUOffsetX = GFX_ALIGN(*pUOffsetX, TileWidth);
405 *pUOffsetY = GFX_ALIGN(*pUOffsetY, TileHeight);
406 *pVOffsetX = GFX_ALIGN(*pVOffsetX, TileWidth);
407 *pVOffsetY = GFX_ALIGN(*pVOffsetY, TileHeight);
408 }
409
410 GMM_DPF_EXIT;
411
412 #undef SWAP_UV
413 }
414
415 /////////////////////////////////////////////////////////////////////////////////////
416 /// Returns the mip offset of given LOD in Mip Tail
417 ///
418 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
419 /// MipLevel: mip-map level
420 ///
421 /// @return offset value of LOD in bytes
422 /////////////////////////////////////////////////////////////////////////////////////
GetMipTailByteOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel)423 uint32_t GmmLib::GmmGen11TextureCalc::GetMipTailByteOffset(GMM_TEXTURE_INFO *pTexInfo,
424 uint32_t MipLevel)
425 {
426 uint32_t ByteOffset = 0, Slot = 0xff;
427
428 GMM_DPF_ENTER;
429
430 // 3D textures follow the Gen10 mip tail format
431 if(!pGmmLibContext->GetSkuTable().FtrStandardMipTailFormat)
432 {
433 return GmmGen9TextureCalc::GetMipTailByteOffset(pTexInfo, MipLevel);
434 }
435
436 if((pTexInfo->Type == RESOURCE_1D) || (pTexInfo->Type == RESOURCE_3D))
437 {
438 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
439 (pTexInfo->Flags.Info.TiledYf ? 4 : 0);
440 }
441 else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
442 {
443 // clang-format off
444 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
445 // TileYs
446 ((pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 16) ? 4 :
447 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 8) ? 3 :
448 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 4) ? 2 :
449 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 2) ? 1 :
450 (pTexInfo->Flags.Info.TiledYs ) ? 0 :
451 // TileYf
452 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 16) ? 11:
453 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 8) ? 10:
454 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 4) ? 8:
455 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 2) ? 5:
456 (pTexInfo->Flags.Info.TiledYf ) ? 4: 0);
457 // clang-format on
458 }
459
460 switch(Slot)
461 {
462 case 0:
463 ByteOffset = GMM_KBYTE(32);
464 break;
465 case 1:
466 ByteOffset = GMM_KBYTE(16);
467 break;
468 case 2:
469 ByteOffset = GMM_KBYTE(8);
470 break;
471 case 3:
472 ByteOffset = GMM_KBYTE(4);
473 break;
474 case 4:
475 ByteOffset = GMM_KBYTE(2);
476 break;
477 case 5:
478 ByteOffset = GMM_BYTES(1536);
479 break;
480 case 6:
481 ByteOffset = GMM_BYTES(1280);
482 break;
483 case 7:
484 ByteOffset = GMM_BYTES(1024);
485 break;
486 case 8:
487 ByteOffset = GMM_BYTES(768);
488 break;
489 case 9:
490 ByteOffset = GMM_BYTES(512);
491 break;
492 case 10:
493 ByteOffset = GMM_BYTES(256);
494 break;
495 case 11:
496 ByteOffset = GMM_BYTES(0);
497 break;
498 case 12:
499 ByteOffset = GMM_BYTES(64);
500 break;
501 case 13:
502 ByteOffset = GMM_BYTES(128);
503 break;
504 case 14:
505 ByteOffset = GMM_BYTES(196);
506 break;
507 default:
508 __GMM_ASSERT(0);
509 }
510
511 GMM_DPF_EXIT;
512
513 return (ByteOffset);
514 }
515
516
517 /////////////////////////////////////////////////////////////////////////////////////
518 /// Returns the mip-map offset in geometric OffsetX, Y, Z for a given LOD in Mip Tail on Gen11.
519 ///
520 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
521 /// MipLevel: mip-map level
522 /// OffsetX: ptr to Offset in X direction (in bytes)
523 /// OffsetY: ptr to Offset in Y direction (in pixels)
524 /// OffsetZ: ptr to Offset in Z direction (in pixels)
525 ///
526 /////////////////////////////////////////////////////////////////////////////////////
527
528 GMM_MIPTAIL_SLOT_OFFSET Gen11MipTailSlotOffset1DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_1D_SURFACE;
529 GMM_MIPTAIL_SLOT_OFFSET Gen11MipTailSlotOffset2DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_2D_SURFACE;
530 GMM_MIPTAIL_SLOT_OFFSET Gen11MipTailSlotOffset3DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_3D_SURFACE;
531
GetMipTailGeometryOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel,uint32_t * OffsetX,uint32_t * OffsetY,uint32_t * OffsetZ)532 void GmmLib::GmmGen11TextureCalc::GetMipTailGeometryOffset(GMM_TEXTURE_INFO *pTexInfo,
533 uint32_t MipLevel,
534 uint32_t * OffsetX,
535 uint32_t * OffsetY,
536 uint32_t * OffsetZ)
537 {
538 uint32_t ArrayIndex = 0;
539 uint32_t Slot = 0;
540
541 GMM_DPF_ENTER;
542
543 switch(pTexInfo->BitsPerPixel)
544 {
545 case 128:
546 ArrayIndex = 0;
547 break;
548 case 64:
549 ArrayIndex = 1;
550 break;
551 case 32:
552 ArrayIndex = 2;
553 break;
554 case 16:
555 ArrayIndex = 3;
556 break;
557 case 8:
558 ArrayIndex = 4;
559 break;
560 default:
561 __GMM_ASSERT(0);
562 break;
563 }
564
565 if(pTexInfo->Type == RESOURCE_1D)
566 {
567 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
568
569 *OffsetX = Gen11MipTailSlotOffset1DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
570 *OffsetY = Gen11MipTailSlotOffset1DSurface[Slot][ArrayIndex].Y;
571 *OffsetZ = Gen11MipTailSlotOffset1DSurface[Slot][ArrayIndex].Z;
572 }
573 else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
574 {
575 // clang-format off
576 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
577 // TileYs
578 ((pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 16) ? 4 :
579 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 8) ? 3 :
580 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 4) ? 2 :
581 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 2) ? 1 :
582 (pTexInfo->Flags.Info.TiledYs) ? 0 :
583 // TileYf
584 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 16) ? 11 :
585 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 8) ? 10 :
586 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 4) ? 8 :
587 (pTexInfo->Flags.Info.TiledYf && pTexInfo->MSAA.NumSamples == 2) ? 5 :
588 (pTexInfo->Flags.Info.TiledYf) ? 4 : 0);
589 // clang-format on
590
591 *OffsetX = Gen11MipTailSlotOffset2DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
592 *OffsetY = Gen11MipTailSlotOffset2DSurface[Slot][ArrayIndex].Y;
593 *OffsetZ = Gen11MipTailSlotOffset2DSurface[Slot][ArrayIndex].Z;
594 }
595 else if(pTexInfo->Type == RESOURCE_3D)
596 {
597 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
598
599 *OffsetX = Gen11MipTailSlotOffset3DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
600 *OffsetY = Gen11MipTailSlotOffset3DSurface[Slot][ArrayIndex].Y;
601 *OffsetZ = Gen11MipTailSlotOffset3DSurface[Slot][ArrayIndex].Z;
602 }
603
604 GMM_DPF_EXIT;
605 return;
606 }
607
FillLinearCCS(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)608 GMM_STATUS GmmLib::GmmGen11TextureCalc::FillLinearCCS(GMM_TEXTURE_INFO * pTexInfo,
609 __GMM_BUFFER_TYPE *pRestrictions)
610 {
611 GMM_GFX_SIZE_T PaddedSize;
612 uint32_t TileHeight;
613 GMM_GFX_SIZE_T YCcsSize = 0;
614 GMM_GFX_SIZE_T UVCcsSize = 0;
615 GMM_GFX_SIZE_T TotalHeight = 0;
616 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
617 GMM_DPF_ENTER;
618
619
620 __GMM_ASSERT(pTexInfo->Flags.Gpu.MMC &&
621 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
622 pTexInfo->Flags.Gpu.__NonMsaaLinearCCS);
623
624 __GMM_ASSERT(pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] > 0);
625 TileHeight = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
626
627 // Vinante : CCS or Tile status buffer is computed by giving 2bit for every 256bytes of origional pixel data.
628 // For YUV Planar surfaces, UV Plane follow immediately after Y plane. Y and UV surfaces have their own
629 // control surfaces. So AuxSurf will be linear buffer with CCS for Y plane followed by CCS for UV plane.
630 // Y and UV control surface must be 4kb base aligned and they store the control data for full tiles covering Y and UV
631 // planes respectively.
632 // GMM will also allocate cacheline aligned 64-byte to hold the LKF's software controlled media compression state.
633 // GMM will calculate YAuxOffset, UVAuxOffset and MediaCompression State offset on the fly. Refer GmmResGetAuxSurfaceOffset().
634
635 YCcsSize = pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] * pTexInfo->Pitch / 1024;
636 YCcsSize = GFX_ALIGN(YCcsSize, PAGE_SIZE);
637
638 if(pTexInfo->ArraySize > 1)
639 {
640 TotalHeight = pTexInfo->OffsetInfo.Plane.ArrayQPitch / pTexInfo->Pitch;
641 }
642 else
643 {
644 TotalHeight = pTexInfo->Size / pTexInfo->Pitch;
645 }
646
647 UVCcsSize = (TotalHeight - pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]) * pTexInfo->Pitch / 1024;
648 UVCcsSize = GFX_ALIGN(UVCcsSize, PAGE_SIZE);
649
650 pTexInfo->Size = GFX_ALIGN(YCcsSize + UVCcsSize + GMM_MEDIA_COMPRESSION_STATE_SIZE, pRestrictions->MinAllocationSize);
651 pTexInfo->Pitch = 0;
652
653 //Store the dimension of linear surface in OffsetInfo.Plane.X.
654 pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = YCcsSize;
655 pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U] =
656 pTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V] = UVCcsSize;
657
658 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] =
659 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] =
660 pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] = 0;
661
662 // Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
663 // is defined by SW requirements; Y plane must be 4KB aligned.
664 if(pTexInfo->ArraySize > 1)
665 {
666 GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
667 int64_t LargeSize;
668
669 // Size should always be page aligned.
670 __GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
671
672 if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
673 {
674 pTexInfo->OffsetInfo.Plane.ArrayQPitch = ElementSizeBytes;
675 pTexInfo->Size = LargeSize;
676 }
677 else
678 {
679 GMM_ASSERTDPF(0, "Surface too large!");
680 return GMM_ERROR;
681 }
682 }
683
684 return GMM_SUCCESS;
685 GMM_DPF_EXIT;
686 }
687
688 /////////////////////////////////////////////////////////////////////////////////////
689 /// This function will Setup a planar surface allocation.
690 ///
691 /// @param[in] pTexInfo: Reference to ::GMM_TEXTURE_INFO
692 /// @param[in] pRestrictions: Reference to surface alignment and size restrictions.
693 ///
694 /// @return ::GMM_STATUS
695 /////////////////////////////////////////////////////////////////////////////////////
FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)696 GMM_STATUS GMM_STDCALL GmmLib::GmmGen11TextureCalc::FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,
697 __GMM_BUFFER_TYPE *pRestrictions)
698 {
699 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
700
701 GMM_DPF_ENTER;
702 uint32_t WidthBytesPhysical, Height, YHeight, VHeight;
703 uint32_t AdjustedVHeight = 0;
704 GMM_STATUS Status;
705 bool UVPacked = false;
706
707 GMM_DPF_ENTER;
708
709 __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
710 __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
711 __GMM_ASSERT(!pTexInfo->Flags.Info.TiledW);
712
713 pTexInfo->TileMode = TILE_NONE;
714
715 WidthBytesPhysical = GFX_ULONG_CAST(pTexInfo->BaseWidth) * pTexInfo->BitsPerPixel >> 3;
716 Height = VHeight = 0;
717
718 YHeight = pTexInfo->BaseHeight;
719
720 //[History]
721 // When planar surfaces are tiled, there are HW alignment
722 // restrictions about where the U and V planes can be located.
723 // Prior to SURFACE_STATE.X/YOffset support, planes needed to start
724 // on tile boundaries; with X/YOffset support, the alignment
725 // restrictions were reduced (but not eliminated).
726 //
727 // Horizontal alignment is only an issue for IMC2/4 surfaces, since
728 // the planes of all other formats are always on the left-edge.
729 //
730 // For IMC1/3 surfaces, we must ensure that both the U/V planes are
731 // properly aligned--That is, both the YHeight and VHeight must be
732 // properly aligned. For all other surfaces (since the U/V data
733 // starts at a common vertical location) only YHeight must be
734 // properly aligned.
735
736 // [Current] :
737 // For Tiled surfaces, even though h/w supports U and V plane alignment
738 // at lower granularities GMM will align all the planes at Tiled boundary
739 // to unify the implementation across all platforms and GMM will add
740 // handling for removing the extra padding when UMDs request for ResCpuBlt
741 // operations.
742 // For Linear surfaces, GMM will continue to support minimal aligment restrictions
743
744 switch(pTexInfo->Format)
745 {
746 case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
747 case GMM_FORMAT_IMC3:
748 case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
749 // YYYYYYYY
750 // YYYYYYYY
751 // YYYYYYYY
752 // YYYYYYYY
753 // UUUU
754 // UUUU
755 // VVVV
756 // VVVV
757 case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
758 // YYYYYYYY
759 // YYYYYYYY
760 // YYYYYYYY
761 // YYYYYYYY
762 // UUUUUUUU
763 // UUUUUUUU
764 // VVVVVVVV
765 // VVVVVVVV
766 {
767 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
768 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
769
770 Height = YHeight + 2 * VHeight; // One VHeight for V and one for U.
771 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
772 break;
773 }
774 case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
775 //YYYYYYYY
776 //YYYYYYYY
777 //YYYYYYYY
778 //YYYYYYYY
779 //UUUUUUUU
780 //VVVVVVVV
781 {
782 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
783
784 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
785
786 Height = YHeight + 2 * VHeight;
787 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
788 break;
789 }
790 case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
791 // YYYYYYYY
792 // YYYYYYYY
793 // YYYYYYYY
794 // YYYYYYYY
795 // UU
796 // UU
797 // UU
798 // UU
799 // VV
800 // VV
801 // VV
802 // VV
803 case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
804 // YYYYYYYY
805 // YYYYYYYY
806 // YYYYYYYY
807 // YYYYYYYY
808 // UUUU
809 // UUUU
810 // UUUU
811 // UUUU
812 // VVVV
813 // VVVV
814 // VVVV
815 // VVVV
816 case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
817 #if _WIN32
818 case GMM_FORMAT_WGBOX_YUV444:
819 case GMM_FORMAT_WGBOX_PLANAR_YUV444:
820 #endif
821 // YYYYYYYY
822 // YYYYYYYY
823 // YYYYYYYY
824 // YYYYYYYY
825 // UUUUUUUU
826 // UUUUUUUU
827 // UUUUUUUU
828 // UUUUUUUU
829 // VVVVVVVV
830 // VVVVVVVV
831 // VVVVVVVV
832 // VVVVVVVV
833 {
834 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
835 VHeight = YHeight;
836
837 Height = YHeight + 2 * VHeight;
838 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
839 break;
840 }
841 case GMM_FORMAT_BGRP:
842 case GMM_FORMAT_RGBP:
843 {
844 //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
845 if(pTexInfo->Flags.Info.Linear)
846 {
847 VHeight = YHeight;
848
849 Height = YHeight + 2 * VHeight;
850 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
851 }
852 else //Tiled
853 {
854 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
855 VHeight = YHeight;
856
857 Height = YHeight + 2 * VHeight;
858 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
859 }
860 break;
861 }
862 case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
863 case GMM_FORMAT_IMC4:
864 {
865 // YYYYYYYY
866 // YYYYYYYY
867 // YYYYYYYY
868 // YYYYYYYY
869 // UUUUVVVV
870 // UUUUVVVV
871
872 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
873 VHeight = GFX_CEIL_DIV(YHeight, 2);
874
875 WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
876
877 Height = YHeight + VHeight;
878
879 // With SURFACE_STATE.XOffset support, the U-V interface has
880 // much lighter restrictions--which will be naturally met by
881 // surface pitch restrictions (i.e. dividing an IMC2/4 pitch
882 // by 2--to get the U/V interface--will always produce a safe
883 // XOffset value).
884
885 // Not technically UV packed but sizing works out the same
886 // if the resource is std swizzled
887 UVPacked = true;
888 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
889
890 break;
891 }
892 case GMM_FORMAT_NV12:
893 case GMM_FORMAT_NV21:
894 case GMM_FORMAT_NV11:
895 case GMM_FORMAT_P010:
896 case GMM_FORMAT_P012:
897 case GMM_FORMAT_P016:
898 case GMM_FORMAT_P208:
899 case GMM_FORMAT_P216:
900 {
901 // YYYYYYYY
902 // YYYYYYYY
903 // YYYYYYYY
904 // YYYYYYYY
905 // [UV-Packing]
906
907 if((pTexInfo->Format == GMM_FORMAT_NV12) ||
908 (pTexInfo->Format == GMM_FORMAT_NV21) ||
909 (pTexInfo->Format == GMM_FORMAT_P010) ||
910 (pTexInfo->Format == GMM_FORMAT_P012) ||
911 (pTexInfo->Format == GMM_FORMAT_P016))
912 {
913 VHeight = GFX_CEIL_DIV(YHeight, 2); // U/V plane half of Y
914 Height = YHeight + VHeight;
915 }
916 else
917 {
918 VHeight = YHeight; // U/V plane is same as Y
919 Height = YHeight + VHeight;
920 }
921
922 if((pTexInfo->Format == GMM_FORMAT_NV12) ||
923 (pTexInfo->Format == GMM_FORMAT_NV21) ||
924 (pTexInfo->Format == GMM_FORMAT_P010) ||
925 (pTexInfo->Format == GMM_FORMAT_P012) ||
926 (pTexInfo->Format == GMM_FORMAT_P016) ||
927 (pTexInfo->Format == GMM_FORMAT_P208) ||
928 (pTexInfo->Format == GMM_FORMAT_P216))
929 {
930 WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
931 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
932 }
933 else //if(pTexInfo->Format == GMM_FORMAT_NV11)
934 {
935 // Tiling not supported, since YPitch != UVPitch...
936 pTexInfo->Flags.Info.TiledY = 0;
937 pTexInfo->Flags.Info.TiledYf = 0;
938 pTexInfo->Flags.Info.TiledYs = 0;
939 pTexInfo->Flags.Info.TiledX = 0;
940 pTexInfo->Flags.Info.Linear = 1;
941 }
942
943 UVPacked = true;
944 break;
945 }
946 case GMM_FORMAT_I420: // IYUV & I420: are identical to YV12 except,
947 case GMM_FORMAT_IYUV: // U & V pl.s are reversed.
948 case GMM_FORMAT_YV12:
949 case GMM_FORMAT_YVU9:
950 {
951 // YYYYYYYY
952 // YYYYYYYY
953 // YYYYYYYY
954 // YYYYYYYY
955 // VVVVVV.. <-- V and U planes follow the Y plane, as linear
956 // ..UUUUUU arrays--without respect to pitch.
957
958 uint32_t YSize, UVSize, YVSizeRShift;
959 uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
960
961 YSize = WidthBytesPhysical * YHeight;
962
963 // YVU9 has one U/V pixel for each 4x4 Y block.
964 // The others have one U/V pixel for each 2x2 Y block.
965
966 // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
967 // The others have a ratio of 4 (2x2 --> 1).
968 YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
969
970 // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
971 // extra/unaligned Y pixels still need corresponding U/V pixels--So
972 // for the purpose of computing the UVSize, we must consider a
973 // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
974 // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
975 YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
976 YSizeForUVPurposes =
977 GFX_ALIGN(WidthBytesPhysical, YSizeForUVPurposesDimensionalAlignment) *
978 GFX_ALIGN(YHeight, YSizeForUVPurposesDimensionalAlignment);
979
980 UVSize = 2 * // <-- U + V
981 (YSizeForUVPurposes >> YVSizeRShift);
982
983 Height = GFX_CEIL_DIV(YSize + UVSize, WidthBytesPhysical);
984
985 // Tiling not supported, since YPitch != UVPitch...
986 pTexInfo->Flags.Info.TiledY = 0;
987 pTexInfo->Flags.Info.TiledYf = 0;
988 pTexInfo->Flags.Info.TiledYs = 0;
989 pTexInfo->Flags.Info.TiledX = 0;
990 pTexInfo->Flags.Info.Linear = 1;
991
992 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 1;
993 break;
994 }
995 default:
996 {
997 GMM_ASSERTDPF(0, "Unexpected format");
998 return GMM_ERROR;
999 }
1000 }
1001
1002 // Align Height to even row to avoid hang if HW over-fetch
1003 Height = GFX_ALIGN(Height, __GMM_EVEN_ROW);
1004
1005 SetTileMode(pTexInfo);
1006
1007 // MMC is not supported for linear formats.
1008 if(pTexInfo->Flags.Gpu.MMC)
1009 {
1010 if(!(pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs))
1011 {
1012 pTexInfo->Flags.Gpu.MMC = 0;
1013 }
1014 }
1015
1016 // Legacy Planar "Linear Video" Restrictions...
1017 if(pTexInfo->Flags.Info.Linear && !pTexInfo->Flags.Wa.NoLegacyPlanarLinearVideoRestrictions)
1018 {
1019 pRestrictions->LockPitchAlignment = GFX_MAX(pRestrictions->LockPitchAlignment, GMM_BYTES(64));
1020 pRestrictions->MinPitch = GFX_MAX(pRestrictions->MinPitch, GMM_BYTES(64));
1021 pRestrictions->PitchAlignment = GFX_MAX(pRestrictions->PitchAlignment, GMM_BYTES(64));
1022 pRestrictions->RenderPitchAlignment = GFX_MAX(pRestrictions->RenderPitchAlignment, GMM_BYTES(64));
1023 }
1024
1025 // Multiply overall pitch alignment for surfaces whose U/V planes have a
1026 // pitch down-scaled from that of Y--Since the U/V pitches must meet the
1027 // original restriction, the Y pitch must meet a scaled-up multiple.
1028 if((pTexInfo->Format == GMM_FORMAT_I420) ||
1029 (pTexInfo->Format == GMM_FORMAT_IYUV) ||
1030 (pTexInfo->Format == GMM_FORMAT_NV11) ||
1031 (pTexInfo->Format == GMM_FORMAT_YV12) ||
1032 (pTexInfo->Format == GMM_FORMAT_YVU9))
1033 {
1034 uint32_t LShift =
1035 (pTexInfo->Format != GMM_FORMAT_YVU9) ?
1036 1 : // UVPitch = 1/2 YPitch
1037 2; // UVPitch = 1/4 YPitch
1038
1039 pRestrictions->LockPitchAlignment <<= LShift;
1040 pRestrictions->MinPitch <<= LShift;
1041 pRestrictions->PitchAlignment <<= LShift;
1042 pRestrictions->RenderPitchAlignment <<= LShift;
1043 }
1044
1045 AdjustedVHeight = VHeight;
1046 // In case of Planar surfaces, only the last Plane has to be aligned to 64 for LCU access
1047 if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU && GmmIsYUVFormatLCUAligned(pTexInfo->Format) && VHeight > 0)
1048 {
1049 AdjustedVHeight = GFX_ALIGN(VHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
1050 Height += AdjustedVHeight - VHeight;
1051 }
1052
1053 // For Tiled Planar surfaces, the planes must be tile-boundary aligned.
1054 // Actual alignment is handled in FillPlanarOffsetAddress, but height
1055 // and width must be adjusted for correct size calculation
1056 if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
1057 {
1058 uint32_t TileHeight = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
1059 uint32_t TileWidth = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
1060
1061 pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
1062
1063 //for separate U and V planes, use U plane unaligned and V plane aligned
1064 Height = GFX_ALIGN(YHeight, TileHeight) + (UVPacked ? GFX_ALIGN(AdjustedVHeight, TileHeight) :
1065 (GFX_ALIGN(VHeight, TileHeight) + GFX_ALIGN(AdjustedVHeight, TileHeight)));
1066
1067 if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
1068 pTexInfo->Format == GMM_FORMAT_IMC4)
1069 {
1070 // If the U & V planes are side-by-side then the surface pitch must be
1071 // padded out so that U and V planes will being on a tile boundary.
1072 // This means that an odd Y plane width must be padded out
1073 // with an additional tile. Even widths do not need padding
1074 uint32_t TileCols = GFX_CEIL_DIV(WidthBytesPhysical, TileWidth);
1075 if(TileCols % 2)
1076 {
1077 WidthBytesPhysical = (TileCols + 1) * TileWidth;
1078 }
1079 }
1080
1081 if(pTexInfo->Flags.Info.TiledYs || pTexInfo->Flags.Info.TiledYf)
1082 {
1083 pTexInfo->Flags.Info.RedecribedPlanes = 1;
1084 }
1085 }
1086
1087 // Vary wide planar tiled planar formats do not support MMC pre gen11. All formats do not support
1088 //Special case LKF MMC compressed surfaces
1089 if(pTexInfo->Flags.Gpu.MMC &&
1090 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
1091 pTexInfo->Flags.Info.TiledY)
1092 {
1093 uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
1094
1095 Height = GFX_ALIGN(YHeight, TileHeight) + GFX_ALIGN(AdjustedVHeight, TileHeight);
1096 }
1097
1098 // Vary wide planar tiled planar formats do not support MMC pre gen11. All formats do not support
1099 // Very wide planar tiled planar formats do not support MMC pre gen11. All formats do not support
1100 // MMC above 16k bytes wide, while Yf NV12 does not support above 8k - 128 bytes.
1101 if((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) <= IGFX_GEN10_CORE) &&
1102 (pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs))
1103 {
1104 if(((pTexInfo->BaseWidth * pTexInfo->BitsPerPixel / 8) >= GMM_KBYTE(16)) ||
1105 (pTexInfo->Format == GMM_FORMAT_NV12 && pTexInfo->Flags.Info.TiledYf &&
1106 (pTexInfo->BaseWidth * pTexInfo->BitsPerPixel / 8) >= (GMM_KBYTE(8) - 128)))
1107 {
1108 pTexInfo->Flags.Gpu.MMC = 0;
1109 }
1110 }
1111
1112 if(pTexInfo->Flags.Info.RedecribedPlanes)
1113 {
1114 if(false == RedescribeTexturePlanes(pTexInfo, &WidthBytesPhysical))
1115 {
1116 __GMM_ASSERT(false);
1117 }
1118 }
1119
1120 if((Status = // <-- Note assignment.
1121 FillTexPitchAndSize(
1122 pTexInfo, WidthBytesPhysical, Height, pRestrictions)) == GMM_SUCCESS)
1123 {
1124 FillPlanarOffsetAddress(pTexInfo);
1125 }
1126
1127 // Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
1128 // is defined by SW requirements; Y plane must be 4KB aligned.
1129 if(pTexInfo->ArraySize > 1)
1130 {
1131 GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
1132 int64_t LargeSize;
1133
1134 // Size should always be page aligned.
1135 __GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
1136
1137 if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
1138 {
1139 pTexInfo->OffsetInfo.Plane.ArrayQPitch = ElementSizeBytes;
1140 pTexInfo->Size = LargeSize;
1141 }
1142 else
1143 {
1144 GMM_ASSERTDPF(0, "Surface too large!");
1145 Status = GMM_ERROR;
1146 }
1147 }
1148
1149 //LKF specific Restrictions
1150 if(GFX_GET_CURRENT_PRODUCT(pPlatform->Platform) == IGFX_LAKEFIELD)
1151 {
1152 // If GMM fall backs TileY to Linear then reset the UnifiedAuxSurface flag.
1153 if(!pTexInfo->Flags.Gpu.MMC &&
1154 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
1155 !pTexInfo->Flags.Gpu.__NonMsaaLinearCCS)
1156 {
1157 GMM_ASSERTDPF(0, "MMC TileY is fallback to Linear surface!");
1158 pTexInfo->Flags.Gpu.UnifiedAuxSurface = 0;
1159 }
1160
1161 if(pTexInfo->Flags.Gpu.MMC &&
1162 pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
1163 pTexInfo->Flags.Gpu.__NonMsaaLinearCCS)
1164 {
1165 FillLinearCCS(pTexInfo, pRestrictions);
1166 }
1167 }
1168
1169 GMM_DPF_EXIT;
1170
1171 return GMM_SUCCESS;
1172 }
1173