xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Texture/GmmTextureAlloc.cpp (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
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 
25 /////////////////////////////////////////////////////////////////////////////////////
26 /// This functions sets the Tile Mode of the graphics surface
27 ///
28 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
29 ///
30 /////////////////////////////////////////////////////////////////////////////////////
SetTileMode(GMM_TEXTURE_INFO * pTexInfo)31 void GmmLib::GmmTextureCalc::SetTileMode(GMM_TEXTURE_INFO *pTexInfo)
32 {
33     const GMM_PLATFORM_INFO *pPlatform;
34 
35     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
36 
37     pTexInfo->TileMode = TILE_NONE;
38 
39     if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags))
40     {
41 // clang-format off
42         #define SET_TILE_MODE(Tile, Submode)                                                \
43         {                                                                                   \
44                 pTexInfo->TileMode =                                                        \
45                     (pTexInfo->BitsPerPixel == 128) ? TILE_##Tile##_##Submode##_128bpe :    \
46                     (pTexInfo->BitsPerPixel ==  64) ? TILE_##Tile##_##Submode##_64bpe  :    \
47                     (pTexInfo->BitsPerPixel ==  32) ? TILE_##Tile##_##Submode##_32bpe  :    \
48                     (pTexInfo->BitsPerPixel ==  16) ? TILE_##Tile##_##Submode##_16bpe  :    \
49                                                       TILE_##Tile##_##Submode##_8bpe;       \
50         }                                                                                   \
51 
52         #define GENERATE_TILE_MODE(T, M1d, M2d, M2d_2x, M2d_4x, M2d_8x, M2d_16x, M3d)            \
53         {\
54             switch (pTexInfo->Type)\
55             {\
56                 case RESOURCE_1D:\
57                     SET_TILE_MODE(T, M1d);\
58                     break;\
59                 case RESOURCE_2D:\
60                 case RESOURCE_CUBE:\
61                     switch (pTexInfo->MSAA.NumSamples)\
62                     {\
63                     case 1:\
64                         SET_TILE_MODE(T, M2d);\
65                         break;\
66                     case 2:\
67                         SET_TILE_MODE(T, M2d_2x);\
68                         break;\
69                     case 4:\
70                         SET_TILE_MODE(T, M2d_4x);\
71                         break;\
72                     case 8:\
73                         SET_TILE_MODE(T, M2d_8x);\
74                         break;\
75                     case 16:\
76                         SET_TILE_MODE(T, M2d_16x);\
77                         break;\
78                     default:\
79                         __GMM_ASSERT(0);\
80                     }\
81                     break;\
82                 case RESOURCE_3D:\
83                     SET_TILE_MODE(T, M3d);\
84                     break;\
85                 default:\
86                     __GMM_ASSERT(0);\
87             }\
88         }
89 
90 
91         // clang-format on
92         if(pTexInfo->Flags.Info.TiledYf)
93         {
94             GENERATE_TILE_MODE(YF, 1D, 2D, 2D_2X, 2D_4X, 2D_8X, 2D_16X, 3D);
95 
96             pTexInfo->Flags.Info.TiledYf = 1;
97             pTexInfo->Flags.Info.TiledYs = 0;
98         }
99         else
100         {
101             if(pGmmLibContext->GetSkuTable().FtrTileY)
102             {
103                 GENERATE_TILE_MODE(YS, 1D, 2D, 2D_2X, 2D_4X, 2D_8X, 2D_16X, 3D);
104             }
105             else
106             {
107                 if (pGmmLibContext->GetSkuTable().FtrXe2PlusTiling)
108                 {
109                     GENERATE_TILE_MODE(_64, 1D, 2D, 2D_2X, 2D_4X, 2D_8X, 2D_16X, 3D);
110                 }
111                 else
112                 {
113                     GENERATE_TILE_MODE(_64, 1D, 2D, 2D_2X, 2D_4X, 2D_4X, 2D_4X, 3D);
114                 }
115             }
116 
117             pTexInfo->Flags.Info.TiledYf = 0;
118             GMM_SET_64KB_TILE(pTexInfo->Flags, 1, pGmmLibContext);
119         }
120 
121 
122         GMM_SET_4KB_TILE(pTexInfo->Flags, pGmmLibContext->GetSkuTable().FtrTileY ? 1 : 0, pGmmLibContext);
123 
124         pTexInfo->Flags.Info.TiledX = 0;
125         pTexInfo->Flags.Info.TiledW = 0;
126         pTexInfo->Flags.Info.Linear = 0;
127 #undef SET_TILE_MODE
128     }
129     else if(GMM_IS_4KB_TILE(pTexInfo->Flags))
130     {
131         GMM_SET_4KB_TILE(pTexInfo->Flags, 1, pGmmLibContext);
132         pTexInfo->Flags.Info.TiledYf = 0;
133         pTexInfo->Flags.Info.TiledYs = 0;
134         pTexInfo->Flags.Info.TiledX  = 0;
135         pTexInfo->Flags.Info.TiledW  = 0;
136         pTexInfo->Flags.Info.Linear  = 0;
137         GMM_SET_4KB_TILE_MODE(pTexInfo->TileMode, pGmmLibContext);
138     }
139     else if(pTexInfo->Flags.Info.TiledX)
140     {
141         pTexInfo->Flags.Info.TiledY  = 0;
142         pTexInfo->Flags.Info.TiledYf = 0;
143         pTexInfo->Flags.Info.TiledYs = 0;
144         pTexInfo->Flags.Info.TiledX  = 1;
145         pTexInfo->Flags.Info.TiledW  = 0;
146         pTexInfo->Flags.Info.Linear  = 0;
147         pTexInfo->TileMode           = LEGACY_TILE_X;
148     }
149     else if(pTexInfo->Flags.Info.TiledW)
150     {
151         pTexInfo->Flags.Info.TiledY  = 0;
152         pTexInfo->Flags.Info.TiledYf = 0;
153         pTexInfo->Flags.Info.TiledYs = 0;
154         pTexInfo->Flags.Info.TiledX  = 0;
155         pTexInfo->Flags.Info.TiledW  = 1;
156         pTexInfo->Flags.Info.Linear  = 0;
157         pTexInfo->TileMode           = LEGACY_TILE_Y;
158     }
159     else if(pTexInfo->Flags.Info.Linear)
160     {
161         pTexInfo->Flags.Info.TiledY  = 0;
162         pTexInfo->Flags.Info.TiledYf = 0;
163         pTexInfo->Flags.Info.TiledYs = 0;
164         pTexInfo->Flags.Info.TiledX  = 0;
165         pTexInfo->Flags.Info.TiledW  = 0;
166         pTexInfo->Flags.Info.Linear  = 1;
167         pTexInfo->TileMode           = TILE_NONE;
168     }
169     else
170     {
171         GMM_ASSERTDPF(0, "No tiling preference set!");
172     }
173 
174     GMM_ASSERTDPF(pTexInfo->TileMode < GMM_TILE_MODES, "Invalid Tile Mode Set");
175 }
176 
177 /////////////////////////////////////////////////////////////////////////////////////
178 /// C Wrapper function for allocating a mip map or planar surface. The function
179 /// outputs offset, size and pitch information by enforcing all the h/w alignment
180 /// and restrictions.
181 ///
182 /// @param[in]  pTexInfo: Reference to GMM_TEXTURE_INFO
183 ///
184 /// @return     ::GMM_STATUS
185 /////////////////////////////////////////////////////////////////////////////////////
186 #if(defined(__GMM_KMD__))
GmmTexAlloc(GMM_LIB_CONTEXT * pGmmLibContext,GMM_TEXTURE_INFO * pTexInfo)187 GMM_STATUS GmmTexAlloc(GMM_LIB_CONTEXT *pGmmLibContext, GMM_TEXTURE_INFO *pTexInfo)
188 {
189     GMM_TEXTURE_CALC *pTextureCalc = pGmmLibContext->GetTextureCalc();
190     return (pTextureCalc->AllocateTexture(pTexInfo));
191 }
192 
GmmTexLinearCCS(GMM_LIB_CONTEXT * pGmmLibContext,GMM_TEXTURE_INFO * pTexInfo,GMM_TEXTURE_INFO * pAuxTexInfo)193 GMM_STATUS GmmTexLinearCCS(GMM_LIB_CONTEXT *pGmmLibContext, GMM_TEXTURE_INFO *pTexInfo, GMM_TEXTURE_INFO *pAuxTexInfo)
194 {
195     GMM_TEXTURE_CALC *pTextureCalc = pGmmLibContext->GetTextureCalc();
196     return (pTextureCalc->FillTexCCS(pTexInfo, pAuxTexInfo));
197 }
198 #endif
199 
200 /////////////////////////////////////////////////////////////////////////////////////
201 /// Top level function for allocating a mip map or planar surface. The function
202 /// outputs offset, size and pitch information by enforcing all the h/w alignment
203 /// and restrictions.
204 ///
205 /// @param[in]  pTexInfo: Reference to GMM_TEXTURE_INFO
206 ///
207 /// @return     ::GMM_STATUS
208 /////////////////////////////////////////////////////////////////////////////////////
AllocateTexture(GMM_TEXTURE_INFO * pTexInfo)209 GMM_STATUS GmmLib::GmmTextureCalc::AllocateTexture(GMM_TEXTURE_INFO *pTexInfo)
210 {
211     __GMM_BUFFER_TYPE Restrictions = {0};
212     GMM_STATUS        Status;
213 
214     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
215     __GMM_ASSERTPTR(pGmmLibContext, GMM_ERROR);
216 
217     GMM_DPF_ENTER;
218 
219     GetTexRestrictions(pTexInfo, &Restrictions);
220 
221     if((Status = __GmmTexFillHAlignVAlign(pTexInfo, pGmmLibContext)) != GMM_SUCCESS)
222     {
223         return Status;
224     }
225 
226     // Planar YUV resources treated special. Packed YUV treated like 2D/3D/Cube...
227     if(GmmIsPlanar(pTexInfo->Format))
228     {
229         Status = FillTexPlanar(pTexInfo, &Restrictions);
230 
231         if((Status == GMM_SUCCESS) &&
232            (ValidateTexInfo(pTexInfo, &Restrictions) == false))
233         {
234             return GMM_ERROR;
235         }
236         if(GMM_SUCCESS != FillTexCCS(pTexInfo, pTexInfo))
237         {
238             return GMM_ERROR;
239         }
240         return Status;
241     }
242     else
243     {
244         SetTileMode(pTexInfo);
245     }
246 
247     switch(pTexInfo->Type)
248     {
249         case RESOURCE_2D:
250         case RESOURCE_PRIMARY:
251         case RESOURCE_SHADOW:
252         case RESOURCE_STAGING:
253         case RESOURCE_GDI:
254         case RESOURCE_NNDI:
255         case RESOURCE_HARDWARE_MBM:
256         case RESOURCE_OVERLAY_INTERMEDIATE_SURFACE:
257         case RESOURCE_IFFS_MAPTOGTT:
258 #if _WIN32
259         case RESOURCE_WGBOX_ENCODE_DISPLAY:
260         case RESOURCE_WGBOX_ENCODE_REFERENCE:
261 #endif
262         {
263             Status = FillTex2D(pTexInfo, &Restrictions);
264 
265             break;
266         }
267         case RESOURCE_1D:
268         {
269             Status = FillTex1D(pTexInfo, &Restrictions);
270 
271             break;
272         }
273         case RESOURCE_3D:
274         {
275             Status = FillTex3D(pTexInfo, &Restrictions);
276 
277             break;
278         }
279         case RESOURCE_CUBE:
280         {
281             Status = FillTexCube(pTexInfo, &Restrictions);
282 
283             break;
284         }
285         case RESOURCE_SCRATCH:
286         case RESOURCE_BUFFER:
287         case RESOURCE_FBC:
288         case RESOURCE_PWR_CONTEXT:
289         case RESOURCE_KMD_BUFFER:
290         case RESOURCE_NULL_CONTEXT_INDIRECT_STATE:
291         case RESOURCE_PERF_DATA_QUEUE:
292         case RESOURCE_HW_CONTEXT:
293         case RESOURCE_TAG_PAGE:
294         case RESOURCE_OVERLAY_DMA:
295         case RESOURCE_GTT_TRANSFER_REGION:
296         case RESOURCE_GLOBAL_BUFFER:
297         case RESOURCE_CURSOR:
298         case RESOURCE_GFX_CLIENT_BUFFER:
299 #if _WIN32
300         case RESOURCE_WGBOX_ENCODE_STATE:
301         case RESOURCE_WGBOX_ENCODE_TFD:
302 #endif
303         {
304             Status = FillTexBlockMem(pTexInfo, &Restrictions);
305             break;
306         }
307         default:
308         {
309             GMM_ASSERTDPF(0, "GmmTexAlloc: Unknown surface type!");
310             return GMM_INVALIDPARAM;
311         }
312     };
313 
314     if(ValidateTexInfo(pTexInfo, &Restrictions) == false)
315     {
316         return GMM_ERROR;
317     }
318 
319     if(GMM_SUCCESS != FillTexCCS(pTexInfo, pTexInfo))
320     {
321         return GMM_ERROR;
322     }
323 
324     return Status;
325 }
326 
FillTexCCS(GMM_TEXTURE_INFO * pBaseSurf,GMM_TEXTURE_INFO * pTexInfo)327 GMM_STATUS GmmLib::GmmTextureCalc::FillTexCCS(GMM_TEXTURE_INFO *pBaseSurf, GMM_TEXTURE_INFO *pTexInfo)
328 {
329     GMM_UNREFERENCED_PARAMETER(pBaseSurf);
330     GMM_UNREFERENCED_PARAMETER(pTexInfo);
331     return GMM_SUCCESS;
332 }
333 
334 /////////////////////////////////////////////////////////////////////////////////////
335 /// This function will validate pTexInfo to make sure all the surface creation
336 /// parameters are valid.
337 ///
338 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
339 /// @param[in]  pRestrictions: Reference to surface alignment and size restrictions
340 ///
341 /// @return     true/false
342 /////////////////////////////////////////////////////////////////////////////////////
ValidateTexInfo(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)343 bool GmmLib::GmmTextureCalc::ValidateTexInfo(GMM_TEXTURE_INFO * pTexInfo,
344                                              __GMM_BUFFER_TYPE *pRestrictions)
345 {
346     __GMM_ASSERTPTR(pTexInfo, false);
347     __GMM_ASSERTPTR(pRestrictions, false);
348 
349     GMM_DPF_ENTER;
350 
351     if(pTexInfo->Pitch > pRestrictions->MaxPitch)
352     {
353         GMM_ASSERTDPF(0,
354                       "GmmLib::GmmTextureCalc::ValidateTexInfo: Pitch"
355                       "exceeds max HW pitch restriction.\r\n");
356         return false;
357     }
358 
359     GMM_DPF_EXIT;
360     return true;
361 }
362 
363 
364 /////////////////////////////////////////////////////////////////////////////////////
365 /// Sets the tiling  type based on the required alignment parameters.
366 ///
367 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
368 /// @param[in]  WidthBytesPhysical: Width in bytes of the surface
369 /// @param[in]  Height: Height of the surface
370 /// @param[in]  pBufferType: Reference to surface alignment and size restrictions
371 ///
372 /// @return     ::GMM_STATUS
373 /////////////////////////////////////////////////////////////////////////////////////
FillTexPitchAndSize(GMM_TEXTURE_INFO * pTexInfo,GMM_GFX_SIZE_T WidthBytesPhysical,uint32_t Height,__GMM_BUFFER_TYPE * pBufferType)374 GMM_STATUS GmmLib::GmmTextureCalc::FillTexPitchAndSize(GMM_TEXTURE_INFO * pTexInfo,
375                                                        GMM_GFX_SIZE_T     WidthBytesPhysical,
376                                                        uint32_t           Height,
377                                                        __GMM_BUFFER_TYPE *pBufferType)
378 {
379     GMM_STATUS     Status           = GMM_SUCCESS;
380     GMM_GFX_SIZE_T WidthBytesRender = 0;
381     GMM_GFX_SIZE_T WidthBytesLock   = 0;
382 
383     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
384     __GMM_ASSERTPTR(pBufferType, GMM_ERROR);
385 
386     GMM_DPF_ENTER;
387 
388     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
389 
390     // Make sure that we meet the minimum HW requirment for that buffer type
391     WidthBytesPhysical = GFX_MAX(WidthBytesPhysical, pBufferType->MinPitch);
392 
393     if(pTexInfo->TileMode >= GMM_TILE_MODES)
394     {
395         GMM_ASSERTDPF(0, "Invalid parameter!");
396         return GMM_ERROR;
397     }
398 
399     if(GMM_ISNOT_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
400     {
401         pTexInfo->LegacyFlags |= GMM_LINEAR;
402 
403         // For linear surace we need to make sure that physical pitch
404         // meet the HW alignment (i.e DWORD or QWORD, ETC)
405         WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical,
406                                        pBufferType->PitchAlignment);
407 
408         WidthBytesRender = WidthBytesPhysical;
409         WidthBytesLock   = WidthBytesPhysical;
410     }
411     else
412     {
413         if(pTexInfo->Flags.Info.TiledY ||
414            pTexInfo->Flags.Info.TiledYf ||
415            pTexInfo->Flags.Info.TiledYs)
416         {
417             pTexInfo->LegacyFlags |= GMM_TILE_Y;
418         }
419         else if(pTexInfo->Flags.Info.TiledX == 1)
420         {
421             pTexInfo->LegacyFlags |= GMM_TILE_X;
422         }
423         else if(pTexInfo->Flags.Info.TiledW == 1)
424         {
425             pTexInfo->LegacyFlags |= GMM_TILE_W;
426         }
427 
428         // Align Height to tile height boundary
429         Height = GFX_ALIGN(Height, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
430 
431         // Align Width to next tile boundary
432         WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical,
433                                        pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth);
434 
435         if(pTexInfo->Flags.Info.RenderCompressed || pTexInfo->Flags.Info.MediaCompressed)
436         {
437             if(!GMM_IS_64KB_TILE(pTexInfo->Flags) && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS) //Ys is naturally aligned to required 4 YF pages
438             {
439                 // Align Pitch to 4-tile boundary
440                 WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical,
441                                                4 * pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth);
442             }
443         }
444 
445         // Calculate Alignment Restriction for rendering on the surface
446         // NOTE:
447         //  WidthBytesPhysical == true physical pitch used to determine amount
448         //                        of Pages need for a surface
449         //  WidthBytesRender == HW require pitch of a surface for rendering
450         //                      (i.e. power2
451         //  WidthBytesLock == Pitch when a surface is visible via Fence region.
452 
453         WidthBytesRender = WidthBytesLock = WidthBytesPhysical;
454 
455         // Align pitch to meet our HW requirment for each buffer
456         WidthBytesRender = GFX_ALIGN(WidthBytesRender,
457                                      pBufferType->RenderPitchAlignment);
458 
459         // Media Memory Compression : Allocate one memory tile wider than is required...
460         pGmmLibContext->GetTextureCalc()->AllocateOneTileThanRequied(pTexInfo, WidthBytesRender,
461                                                                         WidthBytesPhysical, WidthBytesLock);
462 
463         // check if locking a particular suface need to be power 2 or not
464         if(pBufferType->NeedPow2LockAlignment)
465         {
466             WidthBytesLock = GFX_POW2_SIZE(WidthBytesPhysical);
467         }
468 
469         // Align pitch to meet our HW requirment for each buffer
470         // [1] 8K lock pitch is needed on Gen3 when we internally remap the
471         //     display surface in GmmGetDisplayStartAddress ( ). Gen4,
472         //     we don't remap due to Persurface tiling and stick to 64byte
473         //     lock pitch alignment.
474         WidthBytesLock = GFX_ALIGN(WidthBytesLock,
475                                    pBufferType->LockPitchAlignment);
476 
477         if((pTexInfo->Type == RESOURCE_PRIMARY) || pTexInfo->Flags.Gpu.FlipChain)
478         {
479             // [2] At creation time, we tell OS the Render size, not
480             //     SurfaceSizePhysical like other surfaces. Therefore, we change
481             //     the SurfaceSizePhysical to match render size for simplicity.
482             WidthBytesPhysical = WidthBytesRender;
483         }
484 
485         if(pGmmLibContext->GetWaTable().WaMsaa8xTileYDepthPitchAlignment &&
486            (pTexInfo->MSAA.NumSamples == 8) &&
487            GMM_IS_4KB_TILE(pTexInfo->Flags) &&
488            pTexInfo->Flags.Gpu.Depth)
489         {
490             WidthBytesLock =
491             WidthBytesRender =
492             WidthBytesPhysical = GFX_ALIGN(WidthBytesLock, GMM_BYTES(256));
493         }
494     }
495 
496     __GMM_ASSERT(WidthBytesLock == WidthBytesPhysical &&
497                  WidthBytesRender == WidthBytesPhysical &&
498                  WidthBytesLock == WidthBytesRender);
499     pTexInfo->Pitch = WidthBytesLock;
500 
501     //VirtualPadding override
502     if(pTexInfo->Flags.Info.AllowVirtualPadding &&
503        pTexInfo->OverridePitch)
504     {
505         pTexInfo->Pitch = pTexInfo->OverridePitch;
506     }
507 
508     // When lossless compression is enabled with plane width greater than 3840 and
509     // horizontal panning, the surface pitch should be a multiple of 4 tiles. Since
510     // GMM doesn't know about lossless compression status at allocation time, here
511     // we apply the WA to all unified aux surfaces.
512     if(pGmmLibContext->GetWaTable().WaLosslessCompressionSurfaceStride &&
513        pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
514        (pTexInfo->BaseWidth > 3840))
515     {
516         pTexInfo->Pitch = GFX_ALIGN(pTexInfo->Pitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth * 4);
517     }
518 
519     // If FBC is enabled with a linear surface, the surface pitch should be a multiple of
520     // 8 cache lines (512 bytes). Since GMM doesn't know about FBC status, here we apply
521     // the WA to all linear surfaces.
522     // Xadapter surfaces has to be 128 Bytes aligned and hence we don't want this 512B alignment
523     // for Xadapter. Eventually FBC will be disabled in case of Xadapter Linear surfaces
524     if(pGmmLibContext->GetSkuTable().FtrFbc &&
525        pGmmLibContext->GetWaTable().WaFbcLinearSurfaceStride &&
526        pTexInfo->Flags.Gpu.FlipChain &&
527        pTexInfo->Flags.Info.Linear &&
528        !pTexInfo->Flags.Info.XAdapter)
529     {
530         if(pTexInfo->Flags.Gpu.FlipChainPreferred)
531         {
532             // Moderate down displayable flags if input parameters (.FlipChainPrefered)
533             // deprioritise it, over Pitch alignement in this case.
534             pTexInfo->Flags.Gpu.FlipChain = __GMM_IS_ALIGN(pTexInfo->Pitch, 512);
535         }
536         else
537         {
538             pTexInfo->Pitch = GFX_ALIGN(pTexInfo->Pitch, 512);
539         }
540     }
541 
542     // For CCS Aux Display Surf the surface stride should not exceed 8 times the LogicalTileWidth.
543     if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs && pTexInfo->Flags.Gpu.FlipChain &&
544        (GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE))
545     {
546         __GMM_ASSERT(pTexInfo->Pitch <= (pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth * 8));
547         pTexInfo->Pitch = GFX_MIN(pTexInfo->Pitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth * 8);
548     }
549 
550     if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs &&
551        (pTexInfo->Pitch > pPlatform->TexAlign.CCS.MaxPitchinTiles * pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth))
552     {
553         GMM_ASSERTDPF(0, "Aux Surface pitch too large!");
554         Status = GMM_ERROR;
555     }
556 
557     if(pGmmLibContext->GetWaTable().Wa_15010089951)
558     {
559         // Default Tiling is set to Tile64 on FtrTileY disabled platforms
560         uint8_t IsYUVSurface = ((GmmIsPlanar(pTexInfo->Format) &&
561                                  (!((pTexInfo->Format == GMM_FORMAT_BGRP) || (pTexInfo->Format == GMM_FORMAT_RGBP)))) ||
562                                 (GmmIsYUVPacked(pTexInfo->Format) &&
563                                  !((pTexInfo->Format == GMM_FORMAT_YVYU_2x1) || (pTexInfo->Format == GMM_FORMAT_UYVY_2x1) || (pTexInfo->Format == GMM_FORMAT_UYVY_2x1))));
564 
565         //YCRCB* formats
566         uint8_t IsYCrCbSurface = ((pTexInfo->Format == GMM_FORMAT_YCRCB_NORMAL) ||
567                                   (pTexInfo->Format == GMM_FORMAT_YCRCB_SWAPUV) ||
568                                   (pTexInfo->Format == GMM_FORMAT_YCRCB_SWAPUVY) || (pTexInfo->Format == GMM_FORMAT_YCRCB_SWAPY));
569 
570         // Allocation needs to extend an extra tile in width when pitch is not an odd multiplication
571         // of tile width which is 128 for Tile4 (YUV allocation is forced as Tile4).
572         if(pTexInfo->Flags.Info.Tile4 && (IsYUVSurface || IsYCrCbSurface) &&
573            ((pTexInfo->Pitch / (pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth)) % 2 == 0))
574         {
575             pTexInfo->Pitch = (pTexInfo->Pitch + (pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth));
576         }
577     }
578 
579     // For NV12 Linear FlipChain surfaces, UV plane distance should be 4k Aligned.
580     // Hence make the stride to align to 4k, so that UV distance will be 4k aligned.
581     if(pGmmLibContext->GetWaTable().Wa4kAlignUVOffsetNV12LinearSurface &&
582        (pTexInfo->Format == GMM_FORMAT_NV12 || GmmIsP0xx(pTexInfo->Format)) && pTexInfo->Flags.Info.Linear &&
583        (!pTexInfo->Flags.Info.XAdapter) &&
584        ((pTexInfo->Type == RESOURCE_PRIMARY) || pTexInfo->Flags.Gpu.FlipChain))
585     {
586         if(pTexInfo->Flags.Gpu.FlipChainPreferred)
587         {
588             // Moderate down displayable flags if input parameters (.FlipChainPrefered)
589             // deprioritise it, over Pitch alignement in this case.
590             pTexInfo->Flags.Gpu.FlipChain = __GMM_IS_ALIGN(pTexInfo->Pitch, GMM_KBYTE(4));
591         }
592         else
593         {
594             pTexInfo->Pitch = GFX_ALIGN(pTexInfo->Pitch, GMM_KBYTE(4));
595         }
596     }
597 
598     if((GFX_GET_CURRENT_PRODUCT(pPlatform->Platform) >= IGFX_METEORLAKE))
599     {
600         pTexInfo->OffsetInfo.PlaneXe_LPG.PhysicalPitch = pTexInfo->Pitch;
601     }
602 
603     { // Surface Sizes
604         int64_t Size;
605 
606         if(pTexInfo->Flags.Gpu.S3d)
607         {
608             if(pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d) // BDW+ Display Engine S3D (Tiled)
609             {
610                 __GMM_ASSERT(!pTexInfo->Flags.Info.Linear);
611 
612                 pTexInfo->S3d.BlankAreaOffset = 0;
613 
614                 if(pTexInfo->Flags.Gpu.S3dDx && (pTexInfo->ArraySize == 2))
615                 {
616                     pTexInfo->S3d.RFrameOffset     = GFX_ULONG_CAST(pTexInfo->Pitch * pTexInfo->Alignment.QPitch);
617                     pTexInfo->S3d.TallBufferHeight = Height;
618                 }
619                 else
620                 {
621                     if(pTexInfo->Flags.Gpu.Overlay)
622                     {
623                         pTexInfo->S3d.RFrameOffset = GFX_ULONG_CAST(pTexInfo->Pitch * Height);
624 
625                         Height = pTexInfo->S3d.TallBufferHeight = Height * 2;
626                     }
627                     else if(pTexInfo->Flags.Gpu.FlipChain)
628                     {
629                         pTexInfo->S3d.RFrameOffset     = 0;
630                         pTexInfo->S3d.TallBufferHeight = Height;
631                     }
632                     else
633                     {
634                         // Something must be wrong. Not an S3D resource!
635                         __GMM_ASSERT(0);
636                     }
637                 }
638 
639                 __GMM_ASSERT(__GMM_IS_ALIGN(pTexInfo->S3d.RFrameOffset, PAGE_SIZE));
640             }
641             else if(pTexInfo->Flags.Gpu.S3dDx) // DX S3D (Tiled)
642             {
643                 __GMM_ASSERT(!pTexInfo->Flags.Info.Linear || !pTexInfo->Flags.Gpu.Overlay);
644                 __GMM_ASSERT(pTexInfo->ArraySize <= 1); // S3D framebuffer arrays are not supported (pre-BDW).
645 
646                 pTexInfo->S3d.BlankAreaOffset = GFX_ULONG_CAST(pTexInfo->Pitch * pTexInfo->BaseHeight);
647 
648                 pTexInfo->S3d.RFrameOffset =
649                 GFX_ULONG_CAST(pTexInfo->Pitch *
650                                (pTexInfo->S3d.DisplayModeHeight + pTexInfo->S3d.NumBlankActiveLines));
651 
652                 Height =
653                 pTexInfo->S3d.TallBufferHeight =
654                 GFX_ALIGN(
655                 (pTexInfo->BaseHeight * 2) + pTexInfo->S3d.NumBlankActiveLines,
656                 pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
657             }
658             else // Legacy S3D
659             {
660                 __GMM_ASSERT(pTexInfo->Flags.Info.Linear);
661 
662                 pTexInfo->S3d.BlankAreaOffset = GFX_ULONG_CAST(pTexInfo->Pitch * pTexInfo->BaseHeight);
663 
664                 pTexInfo->S3d.RFrameOffset =
665                 GFX_ULONG_CAST(pTexInfo->Pitch *
666                                (pTexInfo->S3d.DisplayModeHeight + pTexInfo->S3d.NumBlankActiveLines));
667 
668                 if(pTexInfo->Flags.Gpu.Overlay)
669                 {
670                     Height =
671                     pTexInfo->S3d.TallBufferHeight =
672                     pTexInfo->BaseHeight +
673                     pTexInfo->S3d.NumBlankActiveLines +
674                     pTexInfo->S3d.DisplayModeHeight;
675                 }
676                 else if(pTexInfo->Flags.Gpu.FlipChain)
677                 {
678                     __GMM_ASSERT(pTexInfo->S3d.DisplayModeHeight == pTexInfo->BaseHeight);
679 
680                     pTexInfo->S3d.TallBufferHeight =
681                     (pTexInfo->BaseHeight * 2) +
682                     pTexInfo->S3d.NumBlankActiveLines;
683                 }
684                 else
685                 {
686                     // Something must be wrong. Not an S3D resource!
687                     __GMM_ASSERT(0);
688                 }
689 
690                 __GMM_ASSERT(__GMM_IS_ALIGN(pTexInfo->S3d.RFrameOffset, PAGE_SIZE));
691                 __GMM_ASSERT(__GMM_IS_ALIGN(pTexInfo->S3d.BlankAreaOffset, PAGE_SIZE));
692             }
693 
694             // Calculate surface size (physical).
695             Size = pTexInfo->Pitch * Height;
696 
697             // Calculate tall buffer size (virtual).
698             pTexInfo->S3d.TallBufferSize = GFX_ULONG_CAST(pTexInfo->Pitch * pTexInfo->S3d.TallBufferHeight);
699         }
700         else
701         {
702             Size = (int64_t)pTexInfo->Pitch * Height;
703 
704             if(pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear)
705             {
706                 Size *= pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth;
707             }
708 
709             if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
710                (pTexInfo->MSAA.NumSamples > 1) &&
711                (pTexInfo->Flags.Gpu.Depth == 0 && pTexInfo->Flags.Gpu.SeparateStencil == 0))
712             {
713                 // For color buffer (meaning not depth or stencil buffer)
714                 // The width/height for TileYf/Ys MSAA surfaces are not expanded (using GmmExpandWidth/Height functions)
715                 // because pitch for these surfaces is in their non-expanded dimensions. So, the pitch
716                 // is also non-expanded units.  That's why, we multiply by the sample size here to get the correct size.
717                 if(pGmmLibContext->GetSkuTable().FtrTileY)
718                 {
719                     Size *= pTexInfo->MSAA.NumSamples;
720                 }
721                 else
722                 {
723                     //XeHP, DG2
724                     if (!pGmmLibContext->GetSkuTable().FtrXe2PlusTiling && (pTexInfo->MSAA.NumSamples == 8 || pTexInfo->MSAA.NumSamples == 16))
725                     {
726                         uint64_t SliceSize = pTexInfo->Pitch * Height;
727                         SliceSize *= 4; // multiple by samples per tile
728                         Size = (int64_t)SliceSize;
729                     }
730                     else
731                     {
732                         Size *= pTexInfo->MSAA.NumSamples;
733                     }
734                 }
735             }
736 
737             if((pTexInfo->Flags.Info.TiledY && pTexInfo->Flags.Gpu.TiledResource))
738             {
739                 //Pad align surface to 64KB ie Tile size
740                 Size = GFX_ALIGN(Size, GMM_KBYTE(64));
741             }
742 
743             if (pGmmLibContext->GetSkuTable().FtrXe2Compression && pTexInfo->Flags.Info.Linear)
744             {
745                 Size = GFX_ALIGN(Size, GMM_BYTES(256)); // for all linear resources starting Xe2, align overall size to compression block size. For subresources, 256B alignment is not needed, needed only for overall resource
746                                                         // on older platforms, all linear resources get Halign = 128B which ensures overall size to be a multiple of compression block size of 128B,
747                                                         // so this is needed only for linear resources on Xe2 where HAlign continues to be at 128B, but compression block size has doubled to 256B
748             }
749 
750             // Buffer Sampler Padding...
751             if((pTexInfo->Type == RESOURCE_BUFFER) &&
752                pGmmLibContext->GetWaTable().WaNoMinimizedTrivialSurfacePadding &&
753                !pTexInfo->Flags.Wa.NoBufferSamplerPadding &&
754                !pTexInfo->Flags.Info.ExistingSysMem && // <-- Currently using separate padding WA in OCL (and rarity/luck in other UMD's).
755                // <-- Never sampled from.
756                !pTexInfo->Flags.Gpu.Query &&
757                !pTexInfo->Flags.Gpu.HistoryBuffer &&
758                !pTexInfo->Flags.Gpu.State &&
759                !pTexInfo->Flags.Gpu.StateDx9ConstantBuffer)
760             // These can be sampled from, so they need the padding...
761             // pTexInfo->Flags.Gpu.Constant
762             // pTexInfo->Flags.Gpu.Index
763             // pTexInfo->Flags.Gpu.Stream
764             // pTexInfo->Flags.Gpu.Vertex
765 
766             {
767                 uint32_t BufferSizeAlignment;
768                 uint32_t BufferSizePadding;
769 
770                 // SURFTYPE_BUFFER's that can be sampled from must have their size
771                 // padded to a multiple of 256 buffer elements and then have an
772                 // additional 16 bytes of padding beyond that. Currently, the GMM
773                 // doesn't receive a buffer's element type/size, so (until that's
774                 // revamped) we'll assume the worst-case of 128-bit elements--which
775                 // means padding to 256 * 128 / 8 = 4KB and then adding 16 bytes.
776                 // In the case of BDW:A0, size is padded to a multiple of 512 buffer
777                 // elements instead of 256--which means padding to 8KB.
778 
779                 BufferSizeAlignment =
780                 (GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE) ?
781                 8192 :
782                 4096;
783 
784                 BufferSizePadding = 16;
785 
786                 Size = GFX_ALIGN(Size, BufferSizeAlignment) + BufferSizePadding;
787             }
788 
789             // HiZ Clear Color requires some small data at the end of the allocation to
790             // store the color data.
791             if(pTexInfo->Flags.Gpu.HiZ && pTexInfo->Flags.Gpu.IndirectClearColor)
792             {
793                 Size += GMM_HIZ_CLEAR_COLOR_SIZE;
794             }
795 
796             if(pTexInfo->Flags.Info.ExistingSysMem &&
797                !pTexInfo->ExistingSysMem.IsGmmAllocated &&
798                !pTexInfo->ExistingSysMem.IsPageAligned)
799             {
800                 // Do not modify Size
801             }
802             else
803             {
804                 Size = GFX_ALIGN(Size, PAGE_SIZE);
805             }
806         }
807 
808         int64_t SurfaceMaxSize = 0;
809 
810         if(pTexInfo->Flags.Gpu.NoRestriction)
811         {
812             SurfaceMaxSize = pPlatform->NoRestriction.MaxWidth;
813         }
814         else if(pTexInfo->Flags.Gpu.TiledResource)
815         {
816             SurfaceMaxSize = GMM_TBYTE(1);
817         }
818         else
819         {
820             SurfaceMaxSize = pPlatform->SurfaceMaxSize;
821         }
822 
823         if(Size <= SurfaceMaxSize)
824         {
825             pTexInfo->Size = Size;
826         }
827         else
828         {
829 #if defined(__GMM_KMD__) || defined(__linux__)
830             GMM_ASSERTDPF(0, "Surface too large!");
831 #endif
832             Status = GMM_ERROR;
833         }
834     }
835 
836     {
837         uint64_t TotalAlignment = (((uint64_t)((uint32_t)(pTexInfo->Alignment.BaseAlignment))) * ((uint32_t)(pBufferType->Alignment)));
838 
839         if(!pTexInfo->Alignment.BaseAlignment || __GMM_IS_ALIGN(pBufferType->Alignment, pTexInfo->Alignment.BaseAlignment))
840         {
841             pTexInfo->Alignment.BaseAlignment = pBufferType->Alignment;
842         }
843         else if(__GMM_IS_ALIGN(pTexInfo->Alignment.BaseAlignment, pBufferType->Alignment))
844         {
845             // Do nothing: pTexInfo->Alignment.BaseAlignment is properly alighned
846         }
847         else if(TotalAlignment > 0xFFFFFFFF)
848         {
849             GMM_ASSERTDPF(0, "Client requested alignment is too high, failing the allocation to match HW requiremnets. \r\n");
850             Status = GMM_ERROR;
851         }
852         else
853         {
854             pTexInfo->Alignment.BaseAlignment = pTexInfo->Alignment.BaseAlignment * pBufferType->Alignment;
855             GMM_ASSERTDPF(0,
856                           "Client requested alignment that is not properly aligned to HW requirements."
857                           "Alignment is going to be much higher to match both client and HW requirements.\r\n");
858         }
859     }
860 
861     if((pTexInfo->Flags.Gpu.TilePool && (GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE)) ||
862        (pTexInfo->Flags.Info.Undefined64KBSwizzle) || GMM_IS_64KB_TILE(pTexInfo->Flags))
863     {
864         pTexInfo->Alignment.BaseAlignment = (GFX_IS_ALIGNED(pTexInfo->Alignment.BaseAlignment, GMM_KBYTE(64))) ? pTexInfo->Alignment.BaseAlignment : GMM_KBYTE(64);
865     }
866 
867     if(pGmmLibContext->GetWaTable().WaCompressedResourceRequiresConstVA21 && pTexInfo->Flags.Gpu.MMC)
868     {
869         pTexInfo->Alignment.BaseAlignment = GMM_MBYTE(4);
870     }
871 
872     GMM_DPF_EXIT;
873 
874     return (Status);
875 } // FillTexPitchAndSize
876 
877 /////////////////////////////////////////////////////////////////////////////////////
878 /// This function will Setup a planar surface allocation.
879 ///
880 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
881 /// @param[in]  pRestrictions: Reference to surface alignment and size restrictions.
882 ///
883 /// @return     ::GMM_STATUS
884 /////////////////////////////////////////////////////////////////////////////////////
FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)885 GMM_STATUS GMM_STDCALL GmmLib::GmmTextureCalc::FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,
886                                                              __GMM_BUFFER_TYPE *pRestrictions)
887 {
888     uint32_t   WidthBytesPhysical, Height, YHeight, VHeight;
889     GMM_STATUS Status;
890     bool       UVPacked = false;
891 
892     GMM_DPF_ENTER;
893 
894     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
895     __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
896     __GMM_ASSERT(!pTexInfo->Flags.Info.TiledW);
897     pTexInfo->TileMode = TILE_NONE;
898 
899     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
900 
901     WidthBytesPhysical = GFX_ULONG_CAST(pTexInfo->BaseWidth) * pTexInfo->BitsPerPixel >> 3;
902     Height = VHeight = 0;
903 
904     YHeight = pTexInfo->BaseHeight;
905 
906     switch(pTexInfo->Format)
907     {
908         case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
909         case GMM_FORMAT_IMC3:
910         case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
911         // YYYYYYYY
912         // YYYYYYYY
913         // YYYYYYYY
914         // YYYYYYYY
915         // UUUU
916         // UUUU
917         // VVVV
918         // VVVV
919         case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
920             // YYYYYYYY
921             // YYYYYYYY
922             // YYYYYYYY
923             // YYYYYYYY
924             // UUUUUUUU
925             // UUUUUUUU
926             // VVVVVVVV
927             // VVVVVVVV
928             {
929                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
930 
931                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
932 
933                 Height = YHeight + 2 * VHeight; // One VHeight for V and one for U.
934 
935                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
936 
937                 break;
938             }
939         case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
940             //YYYYYYYY
941             //YYYYYYYY
942             //YYYYYYYY
943             //YYYYYYYY
944             //UUUUUUUU
945             //VVVVVVVV
946             {
947                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
948 
949                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
950 
951                 Height = YHeight + 2 * VHeight;
952 
953                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
954 
955                 break;
956             }
957         case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
958         // YYYYYYYY
959         // YYYYYYYY
960         // YYYYYYYY
961         // YYYYYYYY
962         // UU
963         // UU
964         // UU
965         // UU
966         // VV
967         // VV
968         // VV
969         // VV
970         case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
971         // YYYYYYYY
972         // YYYYYYYY
973         // YYYYYYYY
974         // YYYYYYYY
975         // UUUU
976         // UUUU
977         // UUUU
978         // UUUU
979         // VVVV
980         // VVVV
981         // VVVV
982         // VVVV
983         case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
984 #if _WIN32
985         case GMM_FORMAT_WGBOX_YUV444:
986         case GMM_FORMAT_WGBOX_PLANAR_YUV444:
987 #endif
988             // YYYYYYYY
989             // YYYYYYYY
990             // YYYYYYYY
991             // YYYYYYYY
992             // UUUUUUUU
993             // UUUUUUUU
994             // UUUUUUUU
995             // UUUUUUUU
996             // VVVVVVVV
997             // VVVVVVVV
998             // VVVVVVVV
999             // VVVVVVVV
1000             {
1001                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
1002                 VHeight = YHeight;
1003 
1004                 Height = YHeight + 2 * VHeight;
1005 
1006                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
1007 
1008                 break;
1009             }
1010         case GMM_FORMAT_BGRP:
1011         case GMM_FORMAT_RGBP:
1012         {
1013             //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
1014             if(pTexInfo->Flags.Info.Linear)
1015             {
1016                 VHeight = YHeight;
1017 
1018                 Height = YHeight + 2 * VHeight;
1019 
1020                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
1021             }
1022             else
1023             {
1024                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
1025                 VHeight = YHeight;
1026 
1027                 Height = YHeight + 2 * VHeight;
1028 
1029                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
1030             }
1031 
1032             break;
1033         }
1034         case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
1035         case GMM_FORMAT_IMC4:
1036         {
1037             // YYYYYYYY
1038             // YYYYYYYY
1039             // YYYYYYYY
1040             // YYYYYYYY
1041             // UUUUVVVV
1042             // UUUUVVVV
1043 
1044             YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
1045             VHeight = GFX_CEIL_DIV(YHeight, 2);
1046 
1047             WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
1048 
1049             Height = YHeight + VHeight;
1050 
1051             // With SURFACE_STATE.XOffset support, the U-V interface has
1052             // much lighter restrictions--which will be naturally met by
1053             // surface pitch restrictions (i.e. dividing an IMC2/4 pitch
1054             // by 2--to get the U/V interface--will always produce a safe
1055             // XOffset value).
1056 
1057             // Not technically UV packed but sizing works out the same
1058             // if the resource is std swizzled
1059             UVPacked                              = true;
1060             pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
1061 
1062             break;
1063         }
1064         case GMM_FORMAT_NV12:
1065         case GMM_FORMAT_NV21:
1066         case GMM_FORMAT_NV11:
1067         case GMM_FORMAT_P010:
1068         case GMM_FORMAT_P012:
1069         case GMM_FORMAT_P016:
1070         case GMM_FORMAT_P208:
1071         case GMM_FORMAT_P216:
1072         {
1073             // YYYYYYYY
1074             // YYYYYYYY
1075             // YYYYYYYY
1076             // YYYYYYYY
1077             // [UV-Packing]
1078             YHeight = GFX_ALIGN(pTexInfo->BaseHeight, __GMM_EVEN_ROW);
1079             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
1080                (pTexInfo->Format == GMM_FORMAT_NV21) ||
1081                (pTexInfo->Format == GMM_FORMAT_P010) ||
1082                (pTexInfo->Format == GMM_FORMAT_P012) ||
1083                (pTexInfo->Format == GMM_FORMAT_P016))
1084             {
1085                 VHeight = GFX_CEIL_DIV(YHeight, 2); // U/V plane half of Y
1086                 Height  = YHeight + VHeight;
1087             }
1088             else
1089             {
1090                 VHeight = YHeight; // U/V plane is same as Y
1091                 Height  = YHeight + VHeight;
1092             }
1093 
1094             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
1095                (pTexInfo->Format == GMM_FORMAT_NV21) ||
1096                (pTexInfo->Format == GMM_FORMAT_P010) ||
1097                (pTexInfo->Format == GMM_FORMAT_P012) ||
1098                (pTexInfo->Format == GMM_FORMAT_P016) ||
1099                (pTexInfo->Format == GMM_FORMAT_P208) ||
1100                (pTexInfo->Format == GMM_FORMAT_P216))
1101             {
1102                 WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
1103             }
1104             else //if(pTexInfo->Format == GMM_FORMAT_NV11)
1105             {
1106                 // Tiling not supported, since YPitch != UVPitch...
1107                 pTexInfo->Flags.Info.TiledY  = 0;
1108                 pTexInfo->Flags.Info.TiledYf = 0;
1109                 pTexInfo->Flags.Info.TiledYs = 0;
1110                 pTexInfo->Flags.Info.TiledX  = 0;
1111                 pTexInfo->Flags.Info.Linear  = 1;
1112             }
1113 
1114             UVPacked                              = true;
1115             pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
1116             break;
1117         }
1118         case GMM_FORMAT_I420: // IYUV & I420: are identical to YV12 except,
1119         case GMM_FORMAT_IYUV: // U & V pl.s are reversed.
1120         case GMM_FORMAT_YV12:
1121         case GMM_FORMAT_YVU9:
1122         {
1123             // YYYYYYYY
1124             // YYYYYYYY
1125             // YYYYYYYY
1126             // YYYYYYYY
1127             // VVVVVV..  <-- V and U planes follow the Y plane, as linear
1128             // ..UUUUUU      arrays--without respect to pitch.
1129 
1130             uint32_t YSize, UVSize, YVSizeRShift;
1131             uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
1132 
1133             YSize = WidthBytesPhysical * YHeight;
1134 
1135             // YVU9 has one U/V pixel for each 4x4 Y block.
1136             // The others have one U/V pixel for each 2x2 Y block.
1137 
1138             // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
1139             // The others have a ratio of 4 (2x2 --> 1).
1140             YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
1141 
1142             // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
1143             // extra/unaligned Y pixels still need corresponding U/V pixels--So
1144             // for the purpose of computing the UVSize, we must consider a
1145             // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
1146             // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
1147             YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
1148             YSizeForUVPurposes =
1149             GFX_ALIGN(WidthBytesPhysical, YSizeForUVPurposesDimensionalAlignment) *
1150             GFX_ALIGN(YHeight, YSizeForUVPurposesDimensionalAlignment);
1151 
1152             UVSize = 2 * // <-- U + V
1153                      (YSizeForUVPurposes >> YVSizeRShift);
1154 
1155             Height = GFX_CEIL_DIV(YSize + UVSize, WidthBytesPhysical);
1156 
1157             // Tiling not supported, since YPitch != UVPitch...
1158             pTexInfo->Flags.Info.TiledY           = 0;
1159             pTexInfo->Flags.Info.TiledYf          = 0;
1160             pTexInfo->Flags.Info.TiledYs          = 0;
1161             pTexInfo->Flags.Info.TiledX           = 0;
1162             pTexInfo->Flags.Info.Linear           = 1;
1163             pTexInfo->OffsetInfo.Plane.NoOfPlanes = 1;
1164             break;
1165         }
1166         default:
1167         {
1168             GMM_ASSERTDPF(0, "Unexpected format");
1169             return GMM_ERROR;
1170         }
1171     }
1172 
1173     // Align Height to even row to avoid hang if HW over-fetch
1174     Height = GFX_ALIGN(Height, __GMM_EVEN_ROW);
1175 
1176     SetTileMode(pTexInfo);
1177 
1178     // MMC is not supported for linear formats.
1179     if(pTexInfo->Flags.Gpu.MMC)
1180     {
1181         if(!(pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs))
1182         {
1183             pTexInfo->Flags.Gpu.MMC = 0;
1184         }
1185     }
1186 
1187     // Legacy Planar "Linear Video" Restrictions...
1188     if(pTexInfo->Flags.Info.Linear && !pTexInfo->Flags.Wa.NoLegacyPlanarLinearVideoRestrictions)
1189     {
1190         pRestrictions->LockPitchAlignment   = GFX_MAX(pRestrictions->LockPitchAlignment, GMM_BYTES(64));
1191         pRestrictions->MinPitch             = GFX_MAX(pRestrictions->MinPitch, GMM_BYTES(64));
1192         pRestrictions->PitchAlignment       = GFX_MAX(pRestrictions->PitchAlignment, GMM_BYTES(64));
1193         pRestrictions->RenderPitchAlignment = GFX_MAX(pRestrictions->RenderPitchAlignment, GMM_BYTES(64));
1194     }
1195 
1196     // Multiply overall pitch alignment for surfaces whose U/V planes have a
1197     // pitch down-scaled from that of Y--Since the U/V pitches must meet the
1198     // original restriction, the Y pitch must meet a scaled-up multiple.
1199     if((pTexInfo->Format == GMM_FORMAT_I420) ||
1200        (pTexInfo->Format == GMM_FORMAT_IYUV) ||
1201        (pTexInfo->Format == GMM_FORMAT_NV11) ||
1202        (pTexInfo->Format == GMM_FORMAT_YV12) ||
1203        (pTexInfo->Format == GMM_FORMAT_YVU9))
1204     {
1205         uint32_t LShift =
1206         (pTexInfo->Format != GMM_FORMAT_YVU9) ?
1207         1 : // UVPitch = 1/2 YPitch
1208         2;  // UVPitch = 1/4 YPitch
1209 
1210         pRestrictions->LockPitchAlignment <<= LShift;
1211         pRestrictions->MinPitch <<= LShift;
1212         pRestrictions->PitchAlignment <<= LShift;
1213         pRestrictions->RenderPitchAlignment <<= LShift;
1214     }
1215 
1216     // For Tiled Planar surfaces, the planes must be tile-boundary aligned.
1217     // Actual alignment is handled in FillPlanarOffsetAddress, but height
1218     // and width must be adjusted for correct size calculation
1219     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
1220     {
1221         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
1222         uint32_t TileWidth  = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
1223 
1224         pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
1225 
1226         Height = GFX_ALIGN(YHeight, TileHeight) + (GFX_ALIGN(VHeight, TileHeight) * (UVPacked ? 1 : 2));
1227 
1228         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
1229            pTexInfo->Format == GMM_FORMAT_IMC4)
1230         {
1231             // If the UV planes are packed then the surface pitch must be
1232             // padded out so that the tile-aligned UV data will fit.
1233             // This means that an odd Y plane width must be padded out
1234             // with an additional tile. Even widths do not need padding
1235             uint32_t TileCols = GFX_CEIL_DIV(WidthBytesPhysical, TileWidth);
1236             if(TileCols % 2)
1237             {
1238                 WidthBytesPhysical = (TileCols + 1) * TileWidth;
1239             }
1240         }
1241 
1242         if(pTexInfo->Flags.Info.TiledYs || pTexInfo->Flags.Info.TiledYf)
1243         {
1244             pTexInfo->Flags.Info.RedecribedPlanes = true;
1245         }
1246     }
1247 
1248     //Special case LKF MMC compressed surfaces
1249     if(pTexInfo->Flags.Gpu.MMC &&
1250        pTexInfo->Flags.Gpu.UnifiedAuxSurface &&
1251        pTexInfo->Flags.Info.TiledY)
1252     {
1253         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
1254 
1255         Height = GFX_ALIGN(YHeight, TileHeight) + GFX_ALIGN(VHeight, TileHeight);
1256     }
1257 
1258     // Vary wide planar tiled planar formats do not support MMC pre gen11. All formats do not support
1259     // MMC above 16k bytes wide, while Yf NV12 does not support above 8k - 128 bytes.
1260     if((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) <= IGFX_GEN10_CORE) &&
1261        (pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs))
1262     {
1263         if(((pTexInfo->BaseWidth * pTexInfo->BitsPerPixel / 8) >= GMM_KBYTE(16)) ||
1264            (pTexInfo->Format == GMM_FORMAT_NV12 && pTexInfo->Flags.Info.TiledYf &&
1265             (pTexInfo->BaseWidth * pTexInfo->BitsPerPixel / 8) >= (GMM_KBYTE(8) - 128)))
1266         {
1267             pTexInfo->Flags.Gpu.MMC = 0;
1268         }
1269     }
1270 
1271     if(pTexInfo->Flags.Info.RedecribedPlanes)
1272     {
1273         if(false == RedescribeTexturePlanes(pTexInfo, &WidthBytesPhysical))
1274         {
1275             __GMM_ASSERT(false);
1276         }
1277     }
1278 
1279     if((Status = // <-- Note assignment.
1280         FillTexPitchAndSize(
1281         pTexInfo, WidthBytesPhysical, Height, pRestrictions)) == GMM_SUCCESS)
1282     {
1283         FillPlanarOffsetAddress(pTexInfo);
1284     }
1285 
1286     // Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
1287     // is defined by SW requirements; Y plane must be 4KB aligned.
1288     if(pTexInfo->ArraySize > 1)
1289     {
1290         GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
1291         int64_t        LargeSize;
1292 
1293         // Size should always be page aligned.
1294         __GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
1295 
1296         if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
1297         {
1298             pTexInfo->OffsetInfo.Plane.ArrayQPitch = ElementSizeBytes;
1299             pTexInfo->Size                         = LargeSize;
1300         }
1301         else
1302         {
1303             GMM_ASSERTDPF(0, "Surface too large!");
1304             Status = GMM_ERROR;
1305         }
1306     }
1307 
1308     GMM_DPF_EXIT;
1309     return (Status);
1310 } // FillTexPlanar
1311 
1312 /////////////////////////////////////////////////////////////////////////////////////
1313 /// This function calculates the size and pitch for the linear buffer based on h/w
1314 /// alignment and size restrictions.
1315 ///
1316 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
1317 /// @param[in]  pRestrictions: Reference to surface alignment and size restrictions
1318 ///
1319 /// @return     ::GMM_STATUS
1320 /////////////////////////////////////////////////////////////////////////////////////
FillTexBlockMem(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)1321 GMM_STATUS GmmLib::GmmTextureCalc::FillTexBlockMem(GMM_TEXTURE_INFO * pTexInfo,
1322                                                    __GMM_BUFFER_TYPE *pRestrictions)
1323 {
1324     GMM_GFX_SIZE_T WidthBytesPhysical;
1325     uint32_t       BitsPerPixel;
1326     GMM_STATUS     Status;
1327 
1328     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
1329     __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
1330     __GMM_ASSERT(pTexInfo->BitsPerPixel == GMM_BITS(8) || (pTexInfo->Flags.Info.AllowVirtualPadding));
1331     __GMM_ASSERT(pTexInfo->BaseHeight == 1);
1332     __GMM_ASSERT(pTexInfo->Flags.Info.Linear == 1);
1333     __GMM_ASSERT(pTexInfo->Flags.Info.TiledW == 0);
1334     __GMM_ASSERT(pTexInfo->Flags.Info.TiledX == 0);
1335     __GMM_ASSERT(pTexInfo->Flags.Info.TiledY == 0);
1336     __GMM_ASSERT(pTexInfo->Flags.Info.TiledYf == 0);
1337     __GMM_ASSERT(pTexInfo->Flags.Info.TiledYs == 0);
1338 
1339     GMM_DPF_ENTER;
1340 
1341     // Width interpreted in bytes.
1342     BitsPerPixel       = pTexInfo->BitsPerPixel;
1343     WidthBytesPhysical = pTexInfo->BaseWidth * BitsPerPixel >> 3;
1344 
1345     Status = GMM_SUCCESS;
1346 
1347     // Clients can allocate Buffers and Structured Buffers by specifying either
1348     // total size (in BaseWidth) or as an array of structs with the ArraySize
1349     // and BaseWidth parameters (where BaseWidth = size of the arrayed struct).
1350     if((pTexInfo->Type == RESOURCE_BUFFER) &&
1351        (pTexInfo->ArraySize > 1))
1352     {
1353         uint64_t __WidthBytesPhysical = WidthBytesPhysical;
1354 
1355         __WidthBytesPhysical *= pTexInfo->ArraySize;
1356 
1357         if(__WidthBytesPhysical <= pRestrictions->MaxPitch)
1358         {
1359             WidthBytesPhysical = (GMM_GFX_SIZE_T)__WidthBytesPhysical;
1360         }
1361         else
1362         {
1363             GMM_ASSERTDPF(0, "Surface too large!");
1364             Status = GMM_ERROR;
1365         }
1366     }
1367 
1368     if(Status == GMM_SUCCESS)
1369     {
1370         // Make sure minimum width and alignment is met.
1371         WidthBytesPhysical = GFX_MAX(WidthBytesPhysical, pRestrictions->MinPitch);
1372         WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, pRestrictions->PitchAlignment);
1373 
1374         Status = FillTexPitchAndSize(pTexInfo, WidthBytesPhysical, pTexInfo->BaseHeight, pRestrictions);
1375     }
1376 
1377     GMM_DPF_EXIT;
1378     return (Status);
1379 }
1380 
1381 
1382 /////////////////////////////////////////////////////////////////////////////////////
1383 /// This function does any special-case conversion from client-provided pseudo creation
1384 /// parameters to actual parameters for CCS.
1385 ///
1386 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
1387 ///
1388 ///  @return     ::GMM_STATUS
1389 /////////////////////////////////////////////////////////////////////////////////////
MSAACCSUsage(GMM_TEXTURE_INFO * pTexInfo)1390 GMM_STATUS GMM_STDCALL GmmLib::GmmTextureCalc::MSAACCSUsage(GMM_TEXTURE_INFO *pTexInfo)
1391 {
1392     GMM_STATUS Status = GMM_SUCCESS;
1393     //const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo);
1394 
1395     if(pTexInfo->MSAA.NumSamples > 1) // CCS for MSAA Compression
1396     {
1397         Status = MSAACompression(pTexInfo);
1398     }
1399     else // Non-MSAA CCS Use (i.e. Render Target Fast Clear)
1400     {
1401         if(!pTexInfo->Flags.Info.TiledW &&
1402            ((!pTexInfo->Flags.Info.Linear) ||
1403             (GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags) ||
1404              (pTexInfo->Type == RESOURCE_BUFFER && pTexInfo->Flags.Info.Linear))) && //!Yf - deprecate Yf
1405            ((pTexInfo->MaxLod == 0) &&
1406             (pTexInfo->ArraySize <= 1)) &&
1407            (((pTexInfo->BitsPerPixel == 32) ||
1408              (pTexInfo->BitsPerPixel == 64) ||
1409              (pTexInfo->BitsPerPixel == 128))))
1410         {
1411             // For non-MSAA CCS usage, the four tables of
1412             // requirements:
1413             // (1) RT Alignment (GMM Don't Care: Occurs Naturally)
1414             // (2) ClearRect Alignment
1415             // (3) ClearRect Scaling (GMM Don't Care: GHAL3D Matter)
1416             // (4) Non-MSAA CCS Sizing
1417 
1418             // Gen8+:
1419             // Since mip-mapped and arrayed surfaces are supported, we
1420             // deal with alignment later at per mip level. Here, we set
1421             // tiling type only. TileX is not supported on Gen9+.
1422             // Pre-Gen8:
1423             // (!) For all the above, there are separate entries for
1424             // 32/64/128bpp--and then deals with PIXEL widths--Here,
1425             // though, we will unify by considering 8bpp table entries
1426             // (unlisted--i.e. do the math)--and deal with BYTE widths.
1427 
1428             // (1) RT Alignment -- The surface width and height don't
1429             // need to be padded to RT CL granularity. On HSW, all tiled
1430             // RT's will have appropriate alignment (given 4KB surface
1431             // base and no mip-map support) and appropriate padding
1432             // (due to tile padding). On BDW+, GMM uses H/VALIGN that
1433             // will guarantee the MCS RT alignment for all subresources.
1434 
1435             // (2) ClearRect Alignment -- I.e. FastClears must be done
1436             // with certain granularity:
1437             //  TileY:  512 Bytes x 128 Lines
1438             //  TileX: 1024 Bytes x  64 Lines
1439             // So a CCS must be sized to match that granularity (though
1440             // the RT itself need not be fully padded to that
1441             // granularity to use FastClear).
1442 
1443             // (4) Non-MSAA CCS Sizing -- CCS sizing is based on the
1444             // size of the FastClear (with granularity padding) for the
1445             // paired RT. CCS's (byte widths and heights) are scaled
1446             // down from their RT's by:
1447             //  TileY: 32 x 32
1448             //  TileX: 64 x 16
1449 
1450             // ### Example #############################################
1451             // RT:         800x600, 32bpp, TileY
1452             // 8bpp:      3200x600
1453             // FastClear: 3584x640 (for TileY FastClear Granularity of 512x128)
1454             // CCS:       112x20 (for TileY RT:CCS Sizing Downscale of 32x32)
1455 
1456             uint32_t AlignmentFactor = pGmmLibContext->GetWaTable().WaDoubleFastClearWidthAlignment ? 2 : 1;
1457 
1458             pTexInfo->BaseWidth    = pTexInfo->BaseWidth * pTexInfo->BitsPerPixel / 8;
1459             pTexInfo->BitsPerPixel = 8;
1460             pTexInfo->Format       = GMM_FORMAT_R8_UINT;
1461 
1462             if(GMM_IS_4KB_TILE(pTexInfo->Flags)) //-------- Fast Clear Granularity
1463             {                                    //                       /--- RT:CCS Sizing Downscale
1464                 pTexInfo->BaseWidth  = GFX_ALIGN(pTexInfo->BaseWidth, 512 * AlignmentFactor) / 32;
1465                 pTexInfo->BaseHeight = GFX_ALIGN(pTexInfo->BaseHeight, 128) / 32;
1466             }
1467             else //if(pTexInfo->Flags.Info.TiledX)
1468             {
1469                 pTexInfo->BaseWidth  = GFX_ALIGN(pTexInfo->BaseWidth, 1024 * AlignmentFactor) / 64;
1470                 pTexInfo->BaseHeight = GFX_ALIGN(pTexInfo->BaseHeight, 64) / 16;
1471             }
1472         }
1473         else
1474         {
1475             GMM_ASSERTDPF(0, "Illegal CCS creation parameters!");
1476             Status = GMM_ERROR;
1477         }
1478     }
1479     return Status;
1480 }
1481 
1482 /////////////////////////////////////////////////////////////////////////////////////
1483 /// This function does any special-case conversion from client-provided pseudo creation
1484 /// parameters to actual parameters for CCS for MSAA Compression.
1485 ///
1486 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
1487 ///
1488 ///  @return     ::GMM_STATUS
1489 /////////////////////////////////////////////////////////////////////////////////////
MSAACompression(GMM_TEXTURE_INFO * pTexInfo)1490 GMM_STATUS GmmLib::GmmTextureCalc::MSAACompression(GMM_TEXTURE_INFO *pTexInfo)
1491 {
1492     GMM_STATUS Status = GMM_SUCCESS;
1493 
1494     if((pTexInfo->MSAA.NumSamples == 2) || (pTexInfo->MSAA.NumSamples == 4))
1495     {
1496         pTexInfo->BitsPerPixel = 8;
1497         pTexInfo->Format       = GMM_FORMAT_R8_UINT;
1498     }
1499     else if(pTexInfo->MSAA.NumSamples == 8)
1500     {
1501         pTexInfo->BitsPerPixel = 32;
1502         pTexInfo->Format       = GMM_FORMAT_R32_UINT;
1503     }
1504     else //if(pTexInfo->MSAA.NumSamples == 16)
1505     {
1506         pTexInfo->BitsPerPixel = 64;
1507         pTexInfo->Format       = GMM_FORMAT_GENERIC_64BIT;
1508     }
1509 
1510     if((Status = __GmmTexFillHAlignVAlign(pTexInfo, pGmmLibContext)) != GMM_SUCCESS) // Need to get our alignment (matching RT) before overwriting our RT's MSAA setting.
1511     {
1512         return Status;
1513     }
1514     pTexInfo->MSAA.NumSamples         = 1; // CCS itself isn't MSAA'ed.
1515     pTexInfo->Flags.Gpu.__MsaaTileMcs = 1;
1516 
1517     return Status;
1518 }
1519 
1520 /////////////////////////////////////////////////////////////////////////////////////
1521 ///Allocate one memory tile wider than is required for Media Memory Compression
1522 ///
1523 /// @param[in]  See function definition.
1524 ///
1525 /// @return     ::
1526 /////////////////////////////////////////////////////////////////////////////////////
AllocateOneTileThanRequied(GMM_TEXTURE_INFO * pTexInfo,GMM_GFX_SIZE_T & WidthBytesRender,GMM_GFX_SIZE_T & WidthBytesPhysical,GMM_GFX_SIZE_T & WidthBytesLock)1527 void GMM_STDCALL GmmLib::GmmTextureCalc::AllocateOneTileThanRequied(GMM_TEXTURE_INFO *pTexInfo,
1528                                                                     GMM_GFX_SIZE_T &  WidthBytesRender,
1529                                                                     GMM_GFX_SIZE_T &  WidthBytesPhysical,
1530                                                                     GMM_GFX_SIZE_T &  WidthBytesLock)
1531 {
1532     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
1533 
1534     if(pTexInfo->Flags.Gpu.MMC && !pTexInfo->Flags.Gpu.UnifiedAuxSurface)
1535     {
1536         WidthBytesRender += pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
1537         WidthBytesPhysical = WidthBytesLock = WidthBytesRender;
1538     }
1539 }
1540