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