xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Texture/GmmGen12Texture.cpp (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
1 /*==============================================================================
2 Copyright(c) 2019 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 
24 #include "Internal/Common/GmmLibInc.h"
25 #include "Internal/Common/Texture/GmmGen10TextureCalc.h"
26 #include "Internal/Common/Texture/GmmGen11TextureCalc.h"
27 #include "Internal/Common/Texture/GmmGen12TextureCalc.h"
28 
29 GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset1DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_1D_SURFACE;
30 GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset2DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_2D_SURFACE;
31 GMM_MIPTAIL_SLOT_OFFSET MipTailSlotOffset3DSurface[15][5] = GEN11_MIPTAIL_SLOT_OFFSET_3D_SURFACE;
32 
33 /////////////////////////////////////////////////////////////////////////////////////
34 /// Calculates height of the 2D mip layout on Gen9
35 ///
36 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO,
37 ///
38 /// @return     height of 2D mip layout
39 /////////////////////////////////////////////////////////////////////////////////////
Get2DMipMapHeight(GMM_TEXTURE_INFO * pTexInfo)40 uint32_t GmmLib::GmmGen12TextureCalc::Get2DMipMapHeight(GMM_TEXTURE_INFO *pTexInfo)
41 {
42     uint32_t BlockHeight, MipHeight;
43     uint32_t HeightLinesLevel0, HeightLinesLevel1, HeightLinesLevel2;
44     uint32_t i, MipLevel, VAlign, CompressHeight, CompressWidth, CompressDepth;
45     uint8_t  Compressed;
46     GMM_DPF_ENTER;
47 
48     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
49 
50     Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
51     MipHeight  = pTexInfo->BaseHeight;
52     MipLevel   = pTexInfo->MaxLod;
53     VAlign     = pTexInfo->Alignment.VAlign;
54     GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
55 
56     HeightLinesLevel0 = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
57 
58     if(Compressed)
59     {
60         HeightLinesLevel0 /= CompressHeight;
61     }
62 
63     // Mip0 height...
64     BlockHeight = HeightLinesLevel0;
65 
66     if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
67        ((pTexInfo->Alignment.MipTailStartLod == 0) || (pTexInfo->MaxLod == 0)))
68     {
69         // Do nothing. Height is already aligned.
70     }
71     else
72     {
73         // Height of Mip1 and Mip2..n needed later...
74         HeightLinesLevel1 = HeightLinesLevel2 = 0;
75         for(i = 1; i <= MipLevel; i++)
76         {
77             uint32_t AlignedHeightLines;
78 
79             if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
80                (i == pTexInfo->Alignment.MipTailStartLod))
81             {
82                 AlignedHeightLines = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
83 
84                 if(i == 1)
85                 {
86                     HeightLinesLevel1 = AlignedHeightLines;
87                 }
88                 else
89                 {
90                     HeightLinesLevel2 += AlignedHeightLines;
91                 }
92 
93                 break;
94             }
95             else
96             {
97                 MipHeight = GmmTexGetMipHeight(pTexInfo, i);
98 
99                 AlignedHeightLines = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
100 
101                 if(Compressed)
102                 {
103                     AlignedHeightLines /= CompressHeight;
104                 }
105 
106                 if(i == 1)
107                 {
108                     HeightLinesLevel1 = AlignedHeightLines;
109                 }
110                 else
111                 {
112                     HeightLinesLevel2 += AlignedHeightLines;
113                 }
114             }
115         }
116 
117         // If Mip1 height covers all others, then that is all we need...
118         if(!(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)))
119         {
120             if(HeightLinesLevel1 >= HeightLinesLevel2)
121             {
122                 BlockHeight += GFX_ALIGN(HeightLinesLevel1, VAlign);
123             }
124             else
125             {
126                 BlockHeight += GFX_ALIGN(HeightLinesLevel2, VAlign);
127             }
128         }
129         else
130         {
131             //TR mode- requires TileMode height alignment
132             BlockHeight += (HeightLinesLevel1 >= HeightLinesLevel2) ? HeightLinesLevel1 : HeightLinesLevel2;
133             BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
134         }
135     }
136 
137     GMM_DPF_EXIT;
138 
139     return (BlockHeight);
140 }
141 
142 /////////////////////////////////////////////////////////////////////////////////////
143 /// Calculates Linear CCS size from main surface size
144 ///
145 /// @param[in]  pSurf: ptr to ::GMM_TEXTURE_INFO of main surface
146 /// @param[in]  pAuxTexInfo: ptr to ::GMM_TEXTURE_INFO of Aux surface
147 ///
148 /////////////////////////////////////////////////////////////////////////////////////
FillTexCCS(GMM_TEXTURE_INFO * pSurf,GMM_TEXTURE_INFO * pAuxTexInfo)149 GMM_STATUS GmmLib::GmmGen12TextureCalc::FillTexCCS(GMM_TEXTURE_INFO *pSurf,
150                                                    GMM_TEXTURE_INFO *pAuxTexInfo)
151 {
152     if(pGmmLibContext->GetSkuTable().FtrFlatPhysCCS && !pSurf->Flags.Gpu.ProceduralTexture)
153     {
154         //No CCS allocation for lossless compression (exclude AMFS CCS).
155         return GMM_SUCCESS;
156     }
157     else if(pAuxTexInfo->Flags.Gpu.__NonMsaaLinearCCS)
158     {
159         GMM_TEXTURE_INFO         Surf      = *pSurf;
160         uint32_t                 Depth;
161         const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pSurf, pGmmLibContext);
162         pAuxTexInfo->Flags.Info.TiledW     = 0;
163         pAuxTexInfo->Flags.Info.TiledYf    = 0;
164         pAuxTexInfo->Flags.Info.TiledX     = 0;
165         pAuxTexInfo->Flags.Info.Linear     = 1;
166         GMM_SET_64KB_TILE(pAuxTexInfo->Flags, 0, pGmmLibContext);
167         GMM_SET_4KB_TILE(pAuxTexInfo->Flags, 0, pGmmLibContext);
168 
169         pAuxTexInfo->ArraySize    = Surf.ArraySize;
170         pAuxTexInfo->Alignment    = {0};
171         pAuxTexInfo->BitsPerPixel = 8;
172         Depth                     = (Surf.Depth > 0) ? Surf.Depth : 1; // Depth = 0 needs to be handled gracefully
173         uint32_t ExpandedArraySize =
174         GFX_MAX(Surf.ArraySize, 1) *
175         ((Surf.Type == RESOURCE_CUBE) ? 6 : 1) *        // Cubemaps simply 6-element, 2D arrays.
176         ((Surf.Type == RESOURCE_3D) ? Depth : 1) * // 3D's simply 2D arrays for sizing.
177         ((Surf.Flags.Gpu.Depth || Surf.Flags.Gpu.SeparateStencil ||
178           GMM_IS_64KB_TILE(Surf.Flags) || Surf.Flags.Info.TiledYf) ?
179          1 :
180          Surf.MSAA.NumSamples) *                                                                                         // MSAA (non-Depth/Stencil) RT samples stored as array planes.
181         ((GMM_IS_64KB_TILE(Surf.Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && !pGmmLibContext->GetSkuTable().FtrXe2PlusTiling && (Surf.MSAA.NumSamples == 16)) ? 4 : // MSAA x8/x16 stored as pseudo array planes each with 4x samples
182          (GMM_IS_64KB_TILE(Surf.Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && !pGmmLibContext->GetSkuTable().FtrXe2PlusTiling && (Surf.MSAA.NumSamples == 8)) ? 2 :
183                                                                                                                                                                        1);
184 
185         if(GMM_IS_64KB_TILE(Surf.Flags) || Surf.Flags.Info.TiledYf)
186         {
187             ExpandedArraySize = GFX_ALIGN(ExpandedArraySize, pPlatform->TileInfo[Surf.TileMode].LogicalTileDepth);
188         }
189 
190         if(GmmIsUVPacked(Surf.Format))
191         {
192             uint64_t YCcsSize = GFX_ALIGN((Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch), GMM_KBYTE(16)) >> 8;
193             YCcsSize          = GFX_ALIGN(YCcsSize, PAGE_SIZE);
194 
195             uint64_t PlanarSize = (Surf.ArraySize > 1) ? (Surf.OffsetInfo.Plane.ArrayQPitch) : Surf.Size;
196 
197             uint64_t UVCcsSize = GFX_ALIGN(PlanarSize - (Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch), GMM_KBYTE(16)) >> 8;
198             if(UVCcsSize == 0)
199             {
200                 //GMM_ASSERTDPF(UVCcsSize != 0, "Incorrect Planar Surface Size"); //Redescription of Yf/Ys planar surface P010 hits it (debug required?)
201                 UVCcsSize = 1;
202             }
203             UVCcsSize = GFX_ALIGN_NP2(UVCcsSize, PAGE_SIZE);
204 
205             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
206             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
207             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U] = YCcsSize; //Being Linear CCS, fill X-offset - Test GetAuxOffset UV_CCS is proper
208             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] = 0;
209             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V] = YCcsSize; //Being Linear CCS, fill X-offset
210             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] = 0;
211 
212             pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch = YCcsSize + UVCcsSize;
213             pAuxTexInfo->Size                         = pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch * ((Surf.ArraySize > 1) ? (Surf.ArraySize) : 1);
214             pAuxTexInfo->Alignment.QPitch = GFX_ULONG_CAST(pAuxTexInfo->Size) / ExpandedArraySize;
215         }
216         else if(GmmIsPlanar(Surf.Format))
217         {
218             //Doesn't require separate Aux surfaces since not displayable. Page-alignment ensures
219             //each hybrid plane is 4k-aligned, hence gets unique AuxT.L1e
220             uint64_t PlanarSize = (Surf.ArraySize > 1) ? (Surf.OffsetInfo.Plane.ArrayQPitch) : Surf.Size;
221             uint64_t CcsSize    = GFX_ALIGN(PlanarSize, GMM_KBYTE(16)) >> 8;
222             CcsSize             = GFX_ALIGN(CcsSize, PAGE_SIZE);
223 
224             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_Y] = 0;
225             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_Y] = 0;
226             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_U] = GFX_ALIGN(Surf.OffsetInfo.Plane.Y[GMM_PLANE_U] * Surf.Pitch, GMM_KBYTE(16)) >> 8; //Being Linear CCS, fill X-offset - Test GetAuxOffset UV_CCS is proper
227             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U] = 0;
228             pAuxTexInfo->OffsetInfo.Plane.X[GMM_PLANE_V] = GFX_ALIGN(Surf.OffsetInfo.Plane.Y[GMM_PLANE_V] * Surf.Pitch, GMM_KBYTE(16)) >> 8; //Being Linear CCS, fill X-offset
229             pAuxTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_V] = 0;
230 
231             pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch = CcsSize;
232             pAuxTexInfo->Size                         = pAuxTexInfo->OffsetInfo.Plane.ArrayQPitch *
233                                 ((Surf.ArraySize > 1) ? (Surf.ArraySize) : 1);
234             pAuxTexInfo->Alignment.QPitch = GFX_ULONG_CAST(pAuxTexInfo->Size) / ExpandedArraySize;
235         }
236         else
237         {
238        	    pAuxTexInfo->Size = (GFX_ALIGN(Surf.Size, GMM_KBYTE(16)) >> 8);
239 
240             uint32_t qPitch;
241             if(ExpandedArraySize > 1)
242             {
243                 uint64_t sliceSize = ((GFX_ALIGN(Surf.Pitch * Surf.Alignment.QPitch, GMM_KBYTE(16)) >> 8));
244                 qPitch             = GFX_ULONG_CAST(sliceSize); //HW doesn't use QPitch for Aux except MCS, how'd AMFS get sw-filled non-zero QPitch?
245 
246 
247                 if(Surf.MSAA.NumSamples && !pGmmLibContext->GetSkuTable().FtrTileY)
248                 {
249                     //MSAA Qpitch is sample-distance, multiply NumSamples in a tile
250                     qPitch *= (pGmmLibContext->GetSkuTable().FtrXe2PlusTiling ? Surf.MSAA.NumSamples : GFX_MIN(Surf.MSAA.NumSamples, 4));
251                 }
252             }
253             else
254             {
255                 qPitch = GFX_ULONG_CAST(pAuxTexInfo->Size);
256             }
257 
258             pAuxTexInfo->Alignment.QPitch = qPitch;
259         }
260         __GMM_ASSERT(ExpandedArraySize || (pAuxTexInfo->Size == 0));
261         pAuxTexInfo->Pitch                   = 0;
262         pAuxTexInfo->Type                    = RESOURCE_BUFFER;
263         pAuxTexInfo->Alignment.BaseAlignment = GMM_KBYTE(4);                            //TODO: TiledResource?
264         pAuxTexInfo->Size                    = GFX_ALIGN(pAuxTexInfo->Size, PAGE_SIZE); //page-align final size
265 
266         if(pAuxTexInfo->Flags.Gpu.TiledResource)
267         {
268             pAuxTexInfo->Alignment.BaseAlignment = GMM_KBYTE(64);                               //TODO: TiledResource?
269             pAuxTexInfo->Size                    = GFX_ALIGN(pAuxTexInfo->Size, GMM_KBYTE(64)); //page-align final size
270         }
271 
272         //Clear compression request in CCS
273         pAuxTexInfo->Flags.Info.RenderCompressed = 0;
274         pAuxTexInfo->Flags.Info.MediaCompressed  = 0;
275         pAuxTexInfo->Flags.Info.NotCompressed    = 1;
276         pAuxTexInfo->Flags.Info.RedecribedPlanes = 0;
277         SetTileMode(pAuxTexInfo);
278 
279         return GMM_SUCCESS;
280     }
281     return GMM_SUCCESS;
282 }
283 
284 /////////////////////////////////////////////////////////////////////////////////////
285 /// Allocates the 2D mip layout for surface state programming.
286 ///
287 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO,
288 /// @param[in]  pRestrictions: ptr to surface alignment and size restrictions
289 ///
290 /// @return     ::GMM_STATUS
291 /////////////////////////////////////////////////////////////////////////////////////
FillTex2D(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)292 GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::FillTex2D(GMM_TEXTURE_INFO * pTexInfo,
293                                                               __GMM_BUFFER_TYPE *pRestrictions)
294 {
295     uint32_t   Width, Height, BitsPerPixel;
296     uint32_t   HAlign, VAlign, DAlign, CompressHeight, CompressWidth, CompressDepth;
297     uint32_t   AlignedWidth, BlockHeight, ExpandedArraySize, Pitch;
298     uint8_t    Compress = 0;
299     GMM_STATUS Status;
300 
301     GMM_DPF_ENTER;
302 
303     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
304     __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
305 
306     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
307 
308     BitsPerPixel = pTexInfo->BitsPerPixel;
309     //TODO: Deprecate TileY usage
310     if((pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs))
311     {
312         // Aux Surfaces are 8bpp.
313         BitsPerPixel = 8;
314     }
315 
316     Height = pTexInfo->BaseHeight;
317     Width  = GFX_ULONG_CAST(pTexInfo->BaseWidth);
318 
319     pTexInfo->MSAA.NumSamples = GFX_MAX(pTexInfo->MSAA.NumSamples, 1);
320 
321     if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags))
322     {
323         FindMipTailStartLod(pTexInfo);
324     }
325 
326     ExpandedArraySize =
327     GFX_MAX(pTexInfo->ArraySize, 1) *
328     ((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1) *             // Cubemaps simply 6-element, 2D arrays.
329     ((pTexInfo->Type == RESOURCE_3D) ? pTexInfo->Depth : 1) * // 3D's simply 2D arrays for sizing.
330     ((pTexInfo->Flags.Gpu.Depth || pTexInfo->Flags.Gpu.SeparateStencil ||
331       (GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)) ? // MSAA Ys/Yf samples are ALSO stored as array planes, calculate size for single sample and expand it later.
332      1 :
333      pTexInfo->MSAA.NumSamples) *                                                                                              // MSAA (non-Depth/Stencil) RT samples stored as array planes.
334     ((pTexInfo->Flags.Gpu.Depth || pTexInfo->Flags.Gpu.SeparateStencil) ? // Depth/Stencil MSAA surface is expanded through Width and Depth
335      1 :
336      ((GMM_IS_64KB_TILE(pTexInfo->Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && !pGmmLibContext->GetSkuTable().FtrXe2PlusTiling && (pTexInfo->MSAA.NumSamples == 16)) ? 4 : // MSAA x8/x16 stored as pseudo array planes each with 4x samples
337       (GMM_IS_64KB_TILE(pTexInfo->Flags) && !pGmmLibContext->GetSkuTable().FtrTileY && !pGmmLibContext->GetSkuTable().FtrXe2PlusTiling && (pTexInfo->MSAA.NumSamples == 8)) ? 2 :
338                                                                                                                                                                               1));
339     if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)
340     {
341         ExpandedArraySize = GFX_CEIL_DIV(ExpandedArraySize, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth);
342     }
343 
344     //
345     // Check for color separation
346     //
347     if(pTexInfo->Flags.Gpu.ColorSeparation || pTexInfo->Flags.Gpu.ColorSeparationRGBX)
348     {
349         bool csRestrictionsMet = (((ExpandedArraySize <= 2) &&
350                                    (ExpandedArraySize == pTexInfo->ArraySize) &&
351                                    ((pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM) ||
352                                     (pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM_SRGB) ||
353                                     (pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM) ||
354                                     (pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM_SRGB) ||
355                                     (pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM) ||
356                                     (pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM_SRGB)) &&
357                                    ((pTexInfo->Flags.Gpu.ColorSeparation && (Width % 16) == 0) ||
358                                     (pTexInfo->Flags.Gpu.ColorSeparationRGBX && (Width % 12) == 0))));
359 
360         if(csRestrictionsMet)
361         {
362             ExpandedArraySize = GMM_COLOR_SEPARATION_ARRAY_SIZE;
363         }
364         else
365         {
366             pTexInfo->Flags.Gpu.ColorSeparation     = 0;
367             pTexInfo->Flags.Gpu.ColorSeparationRGBX = 0;
368         }
369     }
370 
371     HAlign = pTexInfo->Alignment.HAlign;
372     VAlign = pTexInfo->Alignment.VAlign;
373     DAlign = pTexInfo->Alignment.DAlign;
374 
375     GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
376 
377     Compress = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
378 
379     /////////////////////////////////
380     // Calculate Block Surface Height
381     /////////////////////////////////
382 
383     if(ExpandedArraySize > 1)
384     {
385         uint32_t Alignment = VAlign;
386         if((pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear) ||
387            (pTexInfo->Flags.Gpu.S3dDx && pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d) ||
388 	   (pTexInfo->Flags.Wa.MediaPipeUsage))
389         {
390             Alignment = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
391         }
392 
393         // Calculate the overall Block height...Mip0Height + Max(Mip1Height, Sum of Mip2Height..MipnHeight)
394         BlockHeight = Get2DMipMapTotalHeight(pTexInfo);
395         BlockHeight = GFX_ALIGN_NP2(BlockHeight, Alignment);
396 
397         // GMM internally uses QPitch as the logical distance between slices, but translates
398         // as appropriate to service client queries in GmmResGetQPitch.
399         pTexInfo->Alignment.QPitch = BlockHeight;
400 
401         if(Compress)
402         {
403             BlockHeight = GFX_CEIL_DIV(BlockHeight, CompressHeight);
404 
405             BlockHeight = GetAligned3DBlockHeight(pTexInfo, BlockHeight, ExpandedArraySize);
406         }
407         else
408         {
409             BlockHeight = ScaleTextureHeight(pTexInfo, BlockHeight);
410         }
411 
412         BlockHeight *= ExpandedArraySize;
413     }
414     else
415     {
416         pTexInfo->Alignment.QPitch = 0;
417 
418         BlockHeight = Get2DMipMapHeight(pTexInfo);
419         BlockHeight = ScaleTextureHeight(pTexInfo, BlockHeight);
420     }
421 
422     ///////////////////////////////////
423     // Calculate Pitch
424     ///////////////////////////////////
425 
426     AlignedWidth = __GMM_EXPAND_WIDTH(this, Width, HAlign, pTexInfo);
427 
428     // Calculate special pitch case of small dimensions where LOD1 + LOD2 widths
429     // are greater than LOD0. e.g. dimensions 4x4 and MinPitch == 1
430     if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
431        (pTexInfo->Alignment.MipTailStartLod < 2))
432     {
433         // Do nothing -- all mips are in LOD0/LOD1, which is already width aligned.
434     }
435     else if(pTexInfo->MaxLod >= 2)
436     {
437         uint32_t AlignedWidthLod1, AlignedWidthLod2;
438 
439         AlignedWidthLod1 = __GMM_EXPAND_WIDTH(this, Width >> 1, HAlign, pTexInfo);
440         AlignedWidthLod2 = __GMM_EXPAND_WIDTH(this, Width >> 2, HAlign, pTexInfo);
441 
442         AlignedWidth = GFX_MAX(AlignedWidth, AlignedWidthLod1 + AlignedWidthLod2);
443     }
444 
445     if(Compress)
446     {
447         AlignedWidth = GFX_CEIL_DIV(AlignedWidth, CompressWidth);
448     }
449     else
450     {
451         AlignedWidth = ScaleTextureWidth(pTexInfo, AlignedWidth);
452     }
453 
454     // Default pitch
455     Pitch = AlignedWidth * BitsPerPixel >> 3;
456 
457     // Make sure the pitch satisfy linear min pitch requirment
458     Pitch = GFX_MAX(Pitch, pRestrictions->MinPitch);
459 
460     // Make sure pitch satisfy alignment restriction
461     Pitch = GFX_ALIGN(Pitch, pRestrictions->PitchAlignment);
462 
463     ////////////////////
464     // Adjust for Tiling
465     ////////////////////
466 
467     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
468     {
469         Pitch       = GFX_ALIGN(Pitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth);
470         BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
471     }
472 
473     GMM_ASSERTDPF(pTexInfo->Flags.Info.LayoutBelow || !pTexInfo->Flags.Info.LayoutRight, "MIPLAYOUT_RIGHT not supported after Gen6!");
474     pTexInfo->Flags.Info.LayoutBelow = 1;
475     pTexInfo->Flags.Info.LayoutRight = 0;
476 
477     // If a texture is YUV packed, 96, or 48 bpp then one row plus 16 bytes of
478     // padding needs to be added. Since this will create a none pitch aligned
479     // surface the padding is aligned to the next row
480     if(GmmIsYUVPacked(pTexInfo->Format) ||
481        (pTexInfo->BitsPerPixel == GMM_BITS(96)) ||
482        (pTexInfo->BitsPerPixel == GMM_BITS(48)))
483     {
484         BlockHeight += GMM_SCANLINES(1) + GFX_CEIL_DIV(GMM_BYTES(16), Pitch);
485     }
486 
487     // For Non-planar surfaces, the alignment is done on the entire height of the allocation
488     if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU &&
489        GmmIsYUVFormatLCUAligned(pTexInfo->Format) &&
490        !GmmIsPlanar(pTexInfo->Format))
491     {
492         BlockHeight = GFX_ALIGN(BlockHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
493     }
494 
495     // Align height to even row to avoid hang if HW over-fetch
496     BlockHeight = GFX_ALIGN(BlockHeight, __GMM_EVEN_ROW);
497 
498     if((Status = // <-- Note assignment.
499         FillTexPitchAndSize(
500         pTexInfo, Pitch, BlockHeight, pRestrictions)) == GMM_SUCCESS)
501     {
502         Fill2DTexOffsetAddress(pTexInfo);
503     }
504     GMM_DPF_EXIT;
505 
506     return (Status);
507 }
508 
509 /////////////////////////////////////////////////////////////////////////////////////
510 /// This function will Setup a planar surface allocation.
511 ///
512 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
513 /// @param[in]  pRestrictions: Reference to surface alignment and size restrictions.
514 ///
515 /// @return     ::GMM_STATUS
516 /////////////////////////////////////////////////////////////////////////////////////
FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)517 GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::FillTexPlanar(GMM_TEXTURE_INFO * pTexInfo,
518                                                                   __GMM_BUFFER_TYPE *pRestrictions)
519 {
520     uint32_t   WidthBytesPhysical, Height, YHeight, VHeight;
521     uint32_t   AdjustedVHeight = 0;
522     GMM_STATUS Status;
523     bool       UVPacked = false;
524     uint32_t   BitsPerPixel, AlignedWidth;
525 
526     GMM_DPF_ENTER;
527 
528     __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
529     __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
530     __GMM_ASSERT(!pTexInfo->Flags.Info.TiledW);
531     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
532 
533     BitsPerPixel = pTexInfo->BitsPerPixel;
534     AlignedWidth = GFX_ULONG_CAST(pTexInfo->BaseWidth);
535     if(!pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
536     {
537         pTexInfo->TileMode = TILE_NONE;
538     }
539     else
540     {
541         pTexInfo->TileMode = LEGACY_TILE_Y;
542     }
543 
544     WidthBytesPhysical = AlignedWidth * BitsPerPixel >> 3;
545     Height = VHeight = 0;
546 
547     YHeight = pTexInfo->BaseHeight;
548 
549     switch(pTexInfo->Format)
550     {
551         case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
552         case GMM_FORMAT_IMC3:
553         case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
554         // YYYYYYYY
555         // YYYYYYYY
556         // YYYYYYYY
557         // YYYYYYYY
558         // UUUU
559         // UUUU
560         // VVVV
561         // VVVV
562         case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
563             // YYYYYYYY
564             // YYYYYYYY
565             // YYYYYYYY
566             // YYYYYYYY
567             // UUUUUUUU
568             // UUUUUUUU
569             // VVVVVVVV
570             // VVVVVVVV
571             {
572                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
573 
574                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
575 
576                 Height                                = YHeight + 2 * VHeight; // One VHeight for V and one for U.
577                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
578                 break;
579             }
580         case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
581             //YYYYYYYY
582             //YYYYYYYY
583             //YYYYYYYY
584             //YYYYYYYY
585             //UUUUUUUU
586             //VVVVVVVV
587             {
588                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(YHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
589 
590                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
591 
592                 Height                                = YHeight + 2 * VHeight;
593                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
594                 break;
595             }
596         case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
597         // YYYYYYYY
598         // YYYYYYYY
599         // YYYYYYYY
600         // YYYYYYYY
601         // UU
602         // UU
603         // UU
604         // UU
605         // VV
606         // VV
607         // VV
608         // VV
609         case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
610         // YYYYYYYY
611         // YYYYYYYY
612         // YYYYYYYY
613         // YYYYYYYY
614         // UUUU
615         // UUUU
616         // UUUU
617         // UUUU
618         // VVVV
619         // VVVV
620         // VVVV
621         // VVVV
622         case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
623 #if _WIN32
624         case GMM_FORMAT_WGBOX_YUV444:
625         case GMM_FORMAT_WGBOX_PLANAR_YUV444:
626 #endif
627             // YYYYYYYY
628             // YYYYYYYY
629             // YYYYYYYY
630             // YYYYYYYY
631             // UUUUUUUU
632             // UUUUUUUU
633             // UUUUUUUU
634             // UUUUUUUU
635             // VVVVVVVV
636             // VVVVVVVV
637             // VVVVVVVV
638             // VVVVVVVV
639             {
640                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
641                 VHeight = YHeight;
642 
643                 Height                                = YHeight + 2 * VHeight;
644                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
645                 break;
646             }
647         case GMM_FORMAT_BGRP:
648         case GMM_FORMAT_RGBP:
649         {
650             //For RGBP linear Tile keep resource Offset non aligned and for other Tile format to be 16-bit aligned
651             if(pTexInfo->Flags.Info.Linear)
652             {
653                 VHeight = YHeight;
654 
655                 Height                                = YHeight + 2 * VHeight;
656                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
657             }
658             else
659             {
660                 YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
661                 VHeight = YHeight;
662 
663                 Height                                = YHeight + 2 * VHeight;
664                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 3;
665             }
666             break;
667         }
668         case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
669         case GMM_FORMAT_IMC4:
670         {
671             // YYYYYYYY
672             // YYYYYYYY
673             // YYYYYYYY
674             // YYYYYYYY
675             // UUUUVVVV
676             // UUUUVVVV
677 
678             YHeight = GFX_ALIGN(YHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
679             VHeight = GFX_CEIL_DIV(YHeight, 2);
680 
681             WidthBytesPhysical = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
682 
683             Height = YHeight + VHeight;
684 
685             // With SURFACE_STATE.XOffset support, the U-V interface has
686             // much lighter restrictions--which will be naturally met by
687             // surface pitch restrictions (i.e. dividing an IMC2/4 pitch
688             // by 2--to get the U/V interface--will always produce a safe
689             // XOffset value).
690             // Not technically UV packed but sizing works out the same
691             // if the resource is std swizzled
692             UVPacked                              = true;
693             pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
694             break;
695         }
696         case GMM_FORMAT_NV12:
697         case GMM_FORMAT_NV21:
698         case GMM_FORMAT_NV11:
699         case GMM_FORMAT_P010:
700         case GMM_FORMAT_P012:
701         case GMM_FORMAT_P016:
702         case GMM_FORMAT_P208:
703         case GMM_FORMAT_P216:
704         {
705             // YYYYYYYY
706             // YYYYYYYY
707             // YYYYYYYY
708             // YYYYYYYY
709             // [UV-Packing]
710 
711             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
712                (pTexInfo->Format == GMM_FORMAT_NV21) ||
713                (pTexInfo->Format == GMM_FORMAT_P010) ||
714                (pTexInfo->Format == GMM_FORMAT_P012) ||
715                (pTexInfo->Format == GMM_FORMAT_P016))
716             {
717                 VHeight = GFX_CEIL_DIV(YHeight, 2); // U/V plane half of Y
718                 Height  = YHeight + VHeight;
719             }
720             else
721             {
722                 VHeight = YHeight; // U/V plane is same as Y
723                 Height  = YHeight + VHeight;
724             }
725 
726             if((pTexInfo->Format == GMM_FORMAT_NV12) ||
727                (pTexInfo->Format == GMM_FORMAT_NV21) ||
728                (pTexInfo->Format == GMM_FORMAT_P010) ||
729                (pTexInfo->Format == GMM_FORMAT_P012) ||
730                (pTexInfo->Format == GMM_FORMAT_P016) ||
731                (pTexInfo->Format == GMM_FORMAT_P208) ||
732                (pTexInfo->Format == GMM_FORMAT_P216))
733             {
734                 WidthBytesPhysical                    = GFX_ALIGN(WidthBytesPhysical, 2); // If odd YWidth, pitch bumps-up to fit rounded-up U/V planes.
735                 pTexInfo->OffsetInfo.Plane.NoOfPlanes = 2;
736             }
737             else //if(pTexInfo->Format == GMM_FORMAT_NV11)
738             {
739                 // Tiling not supported, since YPitch != UVPitch...
740                 pTexInfo->Flags.Info.TiledYf = 0;
741                 pTexInfo->Flags.Info.TiledX  = 0;
742                 pTexInfo->Flags.Info.Linear  = 1;
743                 GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
744                 GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
745             }
746 
747             UVPacked = true;
748             break;
749         }
750         case GMM_FORMAT_I420: // IYUV & I420: are identical to YV12 except,
751         case GMM_FORMAT_IYUV: // U & V pl.s are reversed.
752         case GMM_FORMAT_YV12:
753         case GMM_FORMAT_YVU9:
754         {
755             // YYYYYYYY
756             // YYYYYYYY
757             // YYYYYYYY
758             // YYYYYYYY
759             // VVVVVV..  <-- V and U planes follow the Y plane, as linear
760             // ..UUUUUU      arrays--without respect to pitch.
761 
762             uint32_t YSize, UVSize, YVSizeRShift;
763             uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
764 
765             YSize = WidthBytesPhysical * YHeight;
766 
767             // YVU9 has one U/V pixel for each 4x4 Y block.
768             // The others have one U/V pixel for each 2x2 Y block.
769 
770             // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
771             // The others have a ratio of 4 (2x2 --> 1).
772             YVSizeRShift = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
773 
774             // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
775             // extra/unaligned Y pixels still need corresponding U/V pixels--So
776             // for the purpose of computing the UVSize, we must consider a
777             // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
778             // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
779             YSizeForUVPurposesDimensionalAlignment = (pTexInfo->Format != GMM_FORMAT_YVU9) ? 2 : 4;
780             YSizeForUVPurposes =
781             GFX_ALIGN(WidthBytesPhysical, YSizeForUVPurposesDimensionalAlignment) *
782             GFX_ALIGN(YHeight, YSizeForUVPurposesDimensionalAlignment);
783 
784             UVSize = 2 * // <-- U + V
785                      (YSizeForUVPurposes >> YVSizeRShift);
786 
787             Height = GFX_CEIL_DIV(YSize + UVSize, WidthBytesPhysical);
788 
789             // Tiling not supported, since YPitch != UVPitch...
790             pTexInfo->Flags.Info.TiledYf          = 0;
791             pTexInfo->Flags.Info.TiledX           = 0;
792             pTexInfo->Flags.Info.Linear           = 1;
793             pTexInfo->OffsetInfo.Plane.NoOfPlanes = 1;
794             GMM_SET_64KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
795             GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
796 
797             break;
798         }
799         default:
800         {
801             GMM_ASSERTDPF(0, "Unexpected format");
802             return GMM_ERROR;
803         }
804     }
805 
806     // Align Height to even row to avoid hang if HW over-fetch
807     Height = GFX_ALIGN(Height, __GMM_EVEN_ROW);
808 
809     SetTileMode(pTexInfo);
810 
811     // If the Surface has Odd height dimension, we will fall back to Linear Format.
812     // If MMC is enabled, disable MMC during such cases.
813     if(pTexInfo->Flags.Gpu.MMC)
814     {
815         if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)))
816         {
817             pTexInfo->Flags.Gpu.MMC = 0;
818         }
819     }
820 
821     // If the Surface has Odd height dimension, we will fall back to Linear Format.
822     // If MMC is enabled, disable .CCS/UnifiedAuxSurface during such cases.
823     if(pTexInfo->Flags.Gpu.CCS)
824     {
825         if(!(GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
826            !(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs && GMM_IS_4KB_TILE(pTexInfo->Flags)))
827         {
828             pTexInfo->Flags.Gpu.MMC               = 0;
829             pTexInfo->Flags.Gpu.CCS               = 0;
830             pTexInfo->Flags.Gpu.UnifiedAuxSurface = 0;
831             pTexInfo->Flags.Gpu.__NonMsaaTileYCcs = 0;
832         }
833     }
834 
835     // Legacy Planar "Linear Video" Restrictions...
836     if(pTexInfo->Flags.Info.Linear && !pTexInfo->Flags.Wa.NoLegacyPlanarLinearVideoRestrictions)
837     {
838         pRestrictions->LockPitchAlignment   = GFX_MAX(pRestrictions->LockPitchAlignment, GMM_BYTES(64));
839         pRestrictions->MinPitch             = GFX_MAX(pRestrictions->MinPitch, GMM_BYTES(64));
840         pRestrictions->PitchAlignment       = GFX_MAX(pRestrictions->PitchAlignment, GMM_BYTES(64));
841         pRestrictions->RenderPitchAlignment = GFX_MAX(pRestrictions->RenderPitchAlignment, GMM_BYTES(64));
842     }
843 
844     // Multiply overall pitch alignment for surfaces whose U/V planes have a
845     // pitch down-scaled from that of Y--Since the U/V pitches must meet the
846     // original restriction, the Y pitch must meet a scaled-up multiple.
847     if((pTexInfo->Format == GMM_FORMAT_I420) ||
848        (pTexInfo->Format == GMM_FORMAT_IYUV) ||
849        (pTexInfo->Format == GMM_FORMAT_NV11) ||
850        (pTexInfo->Format == GMM_FORMAT_YV12) ||
851        (pTexInfo->Format == GMM_FORMAT_YVU9))
852     {
853         uint32_t LShift =
854         (pTexInfo->Format != GMM_FORMAT_YVU9) ?
855         1 : // UVPitch = 1/2 YPitch
856         2;  // UVPitch = 1/4 YPitch
857 
858         pRestrictions->LockPitchAlignment <<= LShift;
859         pRestrictions->MinPitch <<= LShift;
860         pRestrictions->PitchAlignment <<= LShift;
861         pRestrictions->RenderPitchAlignment <<= LShift;
862     }
863 
864     AdjustedVHeight = VHeight;
865 
866     FindMipTailStartLod(pTexInfo);
867 
868     // In case of Planar surfaces, only the last Plane has to be aligned to 64 for LCU access
869     if(pGmmLibContext->GetWaTable().WaAlignYUVResourceToLCU && GmmIsYUVFormatLCUAligned(pTexInfo->Format) && VHeight > 0)
870     {
871         AdjustedVHeight = GFX_ALIGN(VHeight, GMM_SCANLINES(GMM_MAX_LCU_SIZE));
872         Height += AdjustedVHeight - VHeight;
873     }
874 
875     // For std swizzled and UV packed tile Ys/Yf cases, the planes
876     // must be tile-boundary aligned. Actual alignment is handled
877     // in FillPlanarOffsetAddress, but height and width must
878     // be adjusted for correct size calculation
879     if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) &&
880        !pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
881     {
882         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
883         uint32_t TileWidth  = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileWidth;
884 
885         pTexInfo->OffsetInfo.Plane.IsTileAlignedPlanes = true;
886 
887         if(pTexInfo->Flags.Gpu.CCS && !pGmmLibContext->GetSkuTable().FtrFlatPhysCCS) // alignment adjustment needed only for aux tables
888         {
889             if(GMM_IS_64KB_TILE(pTexInfo->Flags))
890             {
891                 TileHeight *= (!WA64K(pGmmLibContext) && !WA16K(pGmmLibContext)) ? 16 : 1; // For 64Kb Tile mode: Multiply TileHeight by 16 for 1 MB alignment
892             }
893             else
894             {
895                 TileHeight *= (WA16K(pGmmLibContext) ? 1 : WA64K(pGmmLibContext) ? 4 : 64); // For 4k Tile:  Multiply TileHeight by 4 and Pitch by 4 for 64kb alignment, multiply TileHeight by 64 and Pitch by 4 for 1 MB alignment
896             }
897         }
898 
899         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
900            pTexInfo->Format == GMM_FORMAT_IMC4)
901         {
902             // If the U & V planes are side-by-side then the surface pitch must be
903             // padded out so that U and V planes will being on a tile boundary.
904             // This means that an odd Y plane width must be padded out
905             // with an additional tile. Even widths do not need padding
906             uint32_t TileCols = GFX_CEIL_DIV(WidthBytesPhysical, TileWidth);
907             if(TileCols % 2)
908             {
909                 WidthBytesPhysical = (TileCols + 1) * TileWidth;
910             }
911         }
912 
913         Height = GFX_ALIGN(YHeight, TileHeight) + (UVPacked ? GFX_ALIGN(AdjustedVHeight, TileHeight) :
914                                                               (GFX_ALIGN(VHeight, TileHeight) + GFX_ALIGN(AdjustedVHeight, TileHeight)));
915 
916         if(GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)
917         {
918             pTexInfo->Flags.Info.RedecribedPlanes = true;
919         }
920     }
921     else if(pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
922     {
923         uint32_t TileHeight = pGmmLibContext->GetPlatformInfo().TileInfo[pTexInfo->TileMode].LogicalTileHeight;
924 
925         BitsPerPixel = 8;
926 
927         if(pTexInfo->Format == GMM_FORMAT_IMC2 || // IMC2, IMC4 needs even tile columns
928            pTexInfo->Format == GMM_FORMAT_IMC4)
929         {
930 // If the U & V planes are side-by-side then the surface pitch must be
931 // padded out so that U and V planes will being on a tile boundary.
932 // This means that an odd Y plane width must be padded out
933 // with an additional tile. Even widths do not need padding
934 
935 // CCS must use padded main surface width, so get main surface TileWidth
936 #define CCSMODE_TO_TILEMODE(y) ((y + TILE_YF_2D_8bpe) < TILE_YS_1D_8bpe) ? (y + TILE_YF_2D_8bpe) : \
937                                                                            ((y + TILE_YF_2D_8bpe + 5) >= TILE_YS_1D_128bpe) ? (y + TILE_YF_2D_8bpe + 5) : TILE_NONE
938 
939             uint32_t BaseTileWidth = pPlatform->TileInfo[CCSMODE_TO_TILEMODE(pTexInfo->CCSModeAlign)].LogicalTileWidth;
940             WidthBytesPhysical     = GFX_ALIGN(WidthBytesPhysical, 2 * BaseTileWidth);
941         }
942 
943         AlignedWidth = GFX_ULONG_CAST(WidthBytesPhysical / (pTexInfo->BitsPerPixel >> 3));
944 
945         WidthBytesPhysical = __GMM_EXPAND_WIDTH(this, AlignedWidth, pTexInfo->Alignment.HAlign, pTexInfo);
946         WidthBytesPhysical = ScaleTextureWidth(pTexInfo, WidthBytesPhysical); //Should both YAux and UVAux use same CCModeALign (ie using common bpe?)
947                                                                               //If different, then copy Aux info from per-plane Aux? HW has separate bpe or common?
948         YHeight = __GMM_EXPAND_HEIGHT(this, YHeight, pTexInfo->Alignment.VAlign, pTexInfo);
949         YHeight = ScaleTextureHeight(pTexInfo, YHeight);
950         YHeight = GFX_ALIGN(YHeight, TileHeight);
951 
952         VHeight = __GMM_EXPAND_HEIGHT(this, VHeight, pTexInfo->Alignment.VAlign, pTexInfo);
953         VHeight = ScaleTextureHeight(pTexInfo, VHeight);
954         VHeight = GFX_ALIGN(VHeight, TileHeight);
955 
956         Height = YHeight + VHeight;
957     }
958 
959     if(pTexInfo->Flags.Info.RedecribedPlanes)
960     {
961         if(false == RedescribeTexturePlanes(pTexInfo, &WidthBytesPhysical))
962         {
963             __GMM_ASSERT(false);
964         }
965     }
966 
967     if((Status = // <-- Note assignment.
968         FillTexPitchAndSize(
969         pTexInfo, WidthBytesPhysical, Height, pRestrictions)) == GMM_SUCCESS)
970     {
971         FillPlanarOffsetAddress(pTexInfo);
972     }
973 
974     // Planar & hybrid 2D arrays supported in DX11.1+ spec but not HW. Memory layout
975     // is defined by SW requirements; Y plane must be 4KB aligned.
976     if(pTexInfo->ArraySize > 1)
977     {
978         GMM_GFX_SIZE_T ElementSizeBytes = pTexInfo->Size;
979         int64_t        LargeSize;
980 
981         // Size should always be page aligned.
982         __GMM_ASSERT((pTexInfo->Size % PAGE_SIZE) == 0);
983 
984         if((LargeSize = (int64_t)ElementSizeBytes * pTexInfo->ArraySize) <= pPlatform->SurfaceMaxSize)
985         {
986             pTexInfo->OffsetInfo.Plane.ArrayQPitch = ElementSizeBytes;
987             pTexInfo->Size                         = LargeSize;
988         }
989         else
990         {
991             GMM_ASSERTDPF(0, "Surface too large!");
992             Status = GMM_ERROR;
993         }
994     }
995 
996     GMM_DPF_EXIT;
997     return (Status);
998 } // FillTexPlanar
999 
GetCCSScaleFactor(GMM_TEXTURE_INFO * pTexInfo,CCS_UNIT & ScaleFactor)1000 GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::GetCCSScaleFactor(GMM_TEXTURE_INFO *pTexInfo,
1001                                                                       CCS_UNIT &        ScaleFactor)
1002 {
1003     GMM_STATUS           Status     = GMM_SUCCESS;
1004     GMM_TEXTURE_ALIGN_EX TexAlignEx = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetExTextureAlign();
1005     uint32_t             CCSModeIdx = 0;
1006 
1007     if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) //pTexInfo is RT Surf
1008     {
1009         CCSModeIdx = CCS_MODE(pTexInfo->TileMode);
1010         __GMM_ASSERT(pTexInfo->TileMode < GMM_TILE_MODES);
1011     }
1012     else //pTexInfo is CCS Surf
1013     {
1014         CCSModeIdx = pTexInfo->CCSModeAlign;
1015     }
1016 
1017     if(!(CCSModeIdx < CCS_MODES))
1018     {
1019         __GMM_ASSERT(0); //indicates something wrong w/ H/V/D Align Filling function or Wrong TileMode set
1020         return GMM_ERROR;
1021     }
1022 
1023     ScaleFactor = TexAlignEx.CCSEx[CCSModeIdx];
1024 
1025     return (Status);
1026 }
1027 
GetCCSExMode(GMM_TEXTURE_INFO * AuxSurf)1028 GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::GetCCSExMode(GMM_TEXTURE_INFO *AuxSurf)
1029 {
1030     if(GMM_IS_4KB_TILE(AuxSurf->Flags) || GMM_IS_64KB_TILE(AuxSurf->Flags) || AuxSurf->Flags.Info.Linear)
1031     {
1032         if(pGmmLibContext->GetSkuTable().FtrLinearCCS)
1033  	{
1034             AuxSurf->Flags.Gpu.__NonMsaaLinearCCS = 1;
1035         }
1036         else
1037         {
1038             AuxSurf->Flags.Gpu.__NonMsaaTileYCcs = 1;
1039             //CCS is always 2D, even for 3D surface
1040             if(AuxSurf->Type == RESOURCE_CUBE)
1041             {
1042                 AuxSurf->ArraySize = 6;
1043             }
1044             AuxSurf->Type = RESOURCE_2D;
1045         }
1046         if(AuxSurf->Flags.Gpu.__NonMsaaTileYCcs)
1047         {
1048             AuxSurf->CCSModeAlign = 0;
1049             SetTileMode(AuxSurf);
1050             /*if (AuxSurf->Flags.Gpu.UnifiedAuxSurface)*/
1051             {
1052                 AuxSurf->CCSModeAlign = CCS_MODE(AuxSurf->TileMode);
1053             }
1054             AuxSurf->TileMode = TILE_NONE;
1055 
1056             __GMM_ASSERT(AuxSurf->CCSModeAlign < CCS_MODES);
1057             return (AuxSurf->CCSModeAlign < CCS_MODES) ? GMM_SUCCESS : GMM_INVALIDPARAM;
1058         }
1059     }
1060     return GMM_SUCCESS;
1061 }
1062 
ScaleTextureHeight(GMM_TEXTURE_INFO * pTexInfo,uint32_t Height)1063 uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleTextureHeight(GMM_TEXTURE_INFO *pTexInfo, uint32_t Height)
1064 {
1065     uint32_t ScaledHeight = Height;
1066     if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
1067     {
1068         CCS_UNIT ScaleFactor;
1069         GetCCSScaleFactor(pTexInfo, ScaleFactor);
1070 
1071         ScaledHeight /= ScaleFactor.Downscale.Height;
1072     }
1073 
1074     return ScaledHeight;
1075 }
1076 
ScaleTextureWidth(GMM_TEXTURE_INFO * pTexInfo,uint32_t Width)1077 uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleTextureWidth(GMM_TEXTURE_INFO *pTexInfo, uint32_t Width)
1078 {
1079     uint32_t ScaledWidth = Width;
1080 
1081     if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
1082     {
1083         CCS_UNIT ScaleFactor;
1084         GetCCSScaleFactor(pTexInfo, ScaleFactor);
1085 
1086 
1087         if(ScaleFactor.Downscale.Width < 0)
1088         {
1089             ScaledWidth *= ((-1) * ScaleFactor.Downscale.Width);
1090         }
1091         else
1092         {
1093             ScaledWidth /= ScaleFactor.Downscale.Width;
1094         }
1095     }
1096     else if(pTexInfo->Flags.Gpu.ColorSeparation)
1097     {
1098         ScaledWidth *= pTexInfo->ArraySize;
1099         __GMM_ASSERT(0 == (ScaledWidth % GMM_COLOR_SEPARATION_WIDTH_DIVISION));
1100         ScaledWidth /= GMM_COLOR_SEPARATION_WIDTH_DIVISION;
1101     }
1102     else if(pTexInfo->Flags.Gpu.ColorSeparationRGBX)
1103     {
1104         ScaledWidth *= pTexInfo->ArraySize;
1105         __GMM_ASSERT(0 == (ScaledWidth % GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION));
1106         ScaledWidth /= GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION;
1107     }
1108 
1109     return ScaledWidth;
1110 }
1111 
ScaleFCRectHeight(GMM_TEXTURE_INFO * pTexInfo,uint32_t Height)1112 uint32_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleFCRectHeight(GMM_TEXTURE_INFO *pTexInfo, uint32_t Height)
1113 {
1114     uint32_t ScaledHeight = Height;
1115     if(pTexInfo->Flags.Gpu.CCS)
1116     {
1117         CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
1118 	uint8_t   index       = FCMaxModes;
1119         if((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
1120         {
1121             ScaledHeight = GFX_ALIGN(ScaledHeight, FCRectAlign[index].Align.Height);
1122             ScaledHeight /= FCRectAlign[index].Downscale.Height;
1123         }
1124         else
1125         {
1126             __GMM_ASSERT(0);
1127         }
1128     }
1129 
1130     return ScaledHeight;
1131 }
1132 
ScaleFCRectWidth(GMM_TEXTURE_INFO * pTexInfo,uint64_t Width)1133 uint64_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::ScaleFCRectWidth(GMM_TEXTURE_INFO *pTexInfo, uint64_t Width)
1134 {
1135     uint64_t ScaledWidth = Width;
1136     if(pTexInfo->Flags.Gpu.CCS)
1137     {
1138         CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
1139         uint8_t   index       = FCMaxModes;
1140         if((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
1141         {
1142             ScaledWidth = GFX_ALIGN(ScaledWidth, FCRectAlign[index].Align.Width);
1143             ScaledWidth /= FCRectAlign[index].Downscale.Width;
1144         }
1145         else
1146         {
1147             //Unsupported tiling-type for FastClear
1148             __GMM_ASSERT(0);
1149         }
1150     }
1151 
1152     return ScaledWidth;
1153 }
1154 
1155 
Get2DFCSurfaceWidthFor3DSurface(GMM_TEXTURE_INFO * pTexInfo,uint64_t Width)1156 uint64_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::Get2DFCSurfaceWidthFor3DSurface(GMM_TEXTURE_INFO *pTexInfo,
1157                                                                                   uint64_t          Width)
1158 {
1159     uint64_t Width2D = Width;
1160     if (pTexInfo->Flags.Gpu.CCS)
1161     {
1162         CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
1163         uint8_t   index       = FCMaxModes;
1164         if ((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
1165         {
1166             Width2D = GFX_ALIGN(Width2D, FCRectAlign[index].Align.Width);
1167             Width2D *= FCRectAlign[index].Downscale.Width;
1168         }
1169         else
1170         {
1171 
1172             __GMM_ASSERT(0);
1173         }
1174     }
1175     return Width2D;
1176 }
Get2DFCSurfaceHeightFor3DSurface(GMM_TEXTURE_INFO * pTexInfo,uint32_t Height,uint32_t Depth)1177 uint64_t GMM_STDCALL GmmLib::GmmGen12TextureCalc::Get2DFCSurfaceHeightFor3DSurface(GMM_TEXTURE_INFO *pTexInfo,
1178                                                                                    uint32_t          Height,
1179                                                                                    uint32_t          Depth)
1180 {
1181     uint64_t Height2D = Height;
1182     uint32_t Depth3D  = Depth;
1183 
1184     if (pTexInfo->Flags.Gpu.CCS && (Depth > 1))
1185     {
1186         CCS_UNIT *FCRectAlign = static_cast<PlatformInfoGen12 *>(pGmmLibContext->GetPlatformInfoObj())->GetFCRectAlign();
1187         uint8_t   index       = FCMaxModes;
1188         if ((index = FCMode(pTexInfo->TileMode, pTexInfo->BitsPerPixel)) < FCMaxModes)
1189         {
1190             Height2D = GFX_ALIGN(Height2D, FCRectAlign[index].Align.Height);
1191             Height2D *= FCRectAlign[index].Downscale.Height;
1192             Depth3D = GFX_ALIGN(Depth3D, FCRectAlign[index].Align.Depth) / FCRectAlign[index].Align.Depth;
1193             Height2D *= Depth3D;
1194         }
1195         else
1196         {
1197 
1198             __GMM_ASSERT(0);
1199         }
1200     }
1201     return Height2D;
1202 }
1203 
1204 /////////////////////////////////////////////////////////////////////////////////////
1205 /// This function does any special-case conversion from client-provided pseudo creation
1206 /// parameters to actual parameters for CCS.
1207 ///
1208 /// @param[in]  pTexInfo: Reference to ::GMM_TEXTURE_INFO
1209 ///
1210 /// @return     ::GMM_STATUS
1211 /////////////////////////////////////////////////////////////////////////////////////
MSAACCSUsage(GMM_TEXTURE_INFO * pTexInfo)1212 GMM_STATUS GMM_STDCALL GmmLib::GmmGen12TextureCalc::MSAACCSUsage(GMM_TEXTURE_INFO *pTexInfo)
1213 {
1214     GMM_STATUS Status = GMM_SUCCESS;
1215 
1216     if(pTexInfo->MSAA.NumSamples > 1 && (pTexInfo->Flags.Gpu.MCS)) // CCS for MSAA Compression
1217     {
1218         Status = MSAACompression(pTexInfo);
1219     }
1220     else // Non-MSAA CCS Use (i.e. Render Target Fast Clear)
1221     {
1222         if(!pTexInfo->Flags.Info.TiledW &&
1223            (!pTexInfo->Flags.Info.TiledX) &&
1224            ((GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags) ||
1225              (pTexInfo->Type == RESOURCE_BUFFER && pTexInfo->Flags.Info.Linear)))) //!Yf - deprecate Yf)
1226         {
1227             // For non-MSAA CCS usage, the Doc has four tables of
1228             // requirements:
1229             // (1) RT Alignment (GMM Don't Care: Occurs Naturally)
1230             // (2) ClearRect Alignment
1231             // (3) ClearRect Scaling (GMM Don't Care: GHAL3D Matter)
1232             // (4) Non-MSAA CCS Sizing
1233 
1234             // Gen8+:
1235             // Since mip-mapped and arrayed surfaces are supported, we
1236             // deal with alignment later at per mip level. Here, we set
1237             // tiling type only. TileX is not supported on Gen9+.
1238             // Pre-Gen8:
1239             // (!) For all the above, the doc has separate entries for
1240             // 32/64/128bpp--and then deals with PIXEL widths--Here,
1241             // though, we will unify by considering 8bpp table entries
1242             // (unlisted--i.e. do the math)--and deal with BYTE widths.
1243 
1244             // (1) RT Alignment -- The surface width and height don't
1245             // need to be padded to RT CL granularity. On HSW, all tiled
1246             // RT's will have appropriate alignment (given 4KB surface
1247             // base and no mip-map support) and appropriate padding
1248             // (due to tile padding). On BDW+, GMM uses H/VALIGN that
1249             // will guarantee the MCS RT alignment for all subresources.
1250 
1251             // (2) ClearRect Alignment -- I.e. FastClears must be done
1252             // with certain granularity:
1253             //  TileY:  512 Bytes x 128 Lines
1254             //  TileX: 1024 Bytes x  64 Lines
1255             // So a CCS must be sized to match that granularity (though
1256             // the RT itself need not be fully padded to that
1257             // granularity to use FastClear).
1258 
1259             // (4) Non-MSAA CCS Sizing -- CCS sizing is based on the
1260             // size of the FastClear (with granularity padding) for the
1261             // paired RT. CCS's (byte widths and heights) are scaled
1262             // down from their RT's by:
1263             //  TileY: 32 x 32
1264             //  TileX: 64 x 16
1265 
1266             // ### Example #############################################
1267             // RT:         800x600, 32bpp, TileY
1268             // 8bpp:      3200x600
1269             // FastClear: 3584x640 (for TileY FastClear Granularity of 512x128)
1270             // CCS:       112x20 (for TileY RT:CCS Sizing Downscale of 32x32)
1271 
1272             GetCCSExMode(pTexInfo);
1273         }
1274         else
1275         {
1276             GMM_ASSERTDPF(0, "Illegal CCS creation parameters!");
1277             Status = GMM_ERROR;
1278         }
1279     }
1280     return Status;
1281 }
1282 
1283 
1284 /////////////////////////////////////////////////////////////////////////////////////
1285 /// Returns the mip offset of given LOD in Mip Tail
1286 ///
1287 /// @param[in]  pTexInfo: ptr to ::GMM_TEXTURE_INFO,
1288 ///             MipLevel: mip-map level
1289 ///
1290 /// @return     offset value of LOD in bytes
1291 /////////////////////////////////////////////////////////////////////////////////////
GetMipTailByteOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel)1292 uint32_t GmmLib::GmmGen12TextureCalc::GetMipTailByteOffset(GMM_TEXTURE_INFO *pTexInfo,
1293                                                            uint32_t          MipLevel)
1294 {
1295     uint32_t ByteOffset = 0, Slot = 0xff;
1296 
1297     GMM_DPF_ENTER;
1298 
1299     if(pGmmLibContext->GetSkuTable().FtrTileY)
1300     {
1301         return GmmGen11TextureCalc::GetMipTailByteOffset(pTexInfo, MipLevel);
1302     }
1303     // 3D textures follow the Gen10 mip tail format
1304     if(!pGmmLibContext->GetSkuTable().FtrStandardMipTailFormat)
1305     {
1306         return GmmGen9TextureCalc::GetMipTailByteOffset(pTexInfo, MipLevel);
1307     }
1308 
1309     // Til64 is the only format which supports MipTail on FtrTileY disabled platforms
1310     __GMM_ASSERT(pTexInfo->Flags.Info.Tile64);
1311     // Mipped MSAA is not supported for Tile64
1312     __GMM_ASSERT(pTexInfo->MSAA.NumSamples <= 1);
1313 
1314     if((pTexInfo->Type == RESOURCE_1D) || (pTexInfo->Type == RESOURCE_3D) || (pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE))
1315     {
1316         Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
1317     }
1318 
1319     // Miptail Slot layout in Tile64: as per specifications
1320     // Byteoffset varies based on bpp for tile64 format, so any caller who needs to use byteoffset needs to call cpuswizzle with corresponding geomteric offsets
1321     // Returning ByteOffset as 0 for Tile64 always
1322 
1323     // GMM_DPF_CRITICAL("Miptail byte offset requested for Tile64 \r\n");
1324     GMM_DPF_EXIT;
1325 
1326     // return ByteOffset=0, i.e return start of miptail for any address within packed miptail
1327     return (ByteOffset);
1328 }
1329 
GetMipTailGeometryOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel,uint32_t * OffsetX,uint32_t * OffsetY,uint32_t * OffsetZ)1330 void GmmLib::GmmGen12TextureCalc::GetMipTailGeometryOffset(GMM_TEXTURE_INFO *pTexInfo,
1331                                                            uint32_t          MipLevel,
1332                                                            uint32_t *        OffsetX,
1333                                                            uint32_t *        OffsetY,
1334                                                            uint32_t *        OffsetZ)
1335 {
1336     uint32_t ArrayIndex = 0;
1337     uint32_t Slot       = 0;
1338 
1339     GMM_DPF_ENTER;
1340 
1341     if(pGmmLibContext->GetSkuTable().FtrTileY)
1342     {
1343         return GmmGen11TextureCalc::GetMipTailGeometryOffset(pTexInfo, MipLevel, OffsetX, OffsetY, OffsetZ);
1344     }
1345 
1346     // Til64 is the only format which supports MipTail on FtrTileY disabled platforms
1347     __GMM_ASSERT(pTexInfo->Flags.Info.Tile64);
1348     // Mipped MSAA is not supported for Tile64
1349     __GMM_ASSERT(pTexInfo->MSAA.NumSamples <= 1);
1350 
1351     switch(pTexInfo->BitsPerPixel)
1352     {
1353         case 128:
1354             ArrayIndex = 0;
1355             break;
1356         case 64:
1357             ArrayIndex = 1;
1358             break;
1359         case 32:
1360             ArrayIndex = 2;
1361             break;
1362         case 16:
1363             ArrayIndex = 3;
1364             break;
1365         case 8:
1366             ArrayIndex = 4;
1367             break;
1368         default:
1369             __GMM_ASSERT(0);
1370             break;
1371     }
1372 
1373 
1374     // FtrTileY disabled platforms: platforms which support Tile4/Tile64 tiled formats
1375     if(pTexInfo->Type == RESOURCE_1D)
1376     {
1377         Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
1378 
1379         *OffsetX = MipTailSlotOffset1DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1380         *OffsetY = MipTailSlotOffset1DSurface[Slot][ArrayIndex].Y;
1381         *OffsetZ = MipTailSlotOffset1DSurface[Slot][ArrayIndex].Z;
1382     }
1383     else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
1384     {
1385         // Mipped MSAA is not supported on Tile64, so need not account for MSAA here
1386         Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
1387 
1388         *OffsetX = MipTailSlotOffset2DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1389         *OffsetY = MipTailSlotOffset2DSurface[Slot][ArrayIndex].Y;
1390         *OffsetZ = MipTailSlotOffset2DSurface[Slot][ArrayIndex].Z;
1391     }
1392     else if(pTexInfo->Type == RESOURCE_3D)
1393     {
1394         Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod;
1395 
1396         *OffsetX = MipTailSlotOffset3DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1397         *OffsetY = MipTailSlotOffset3DSurface[Slot][ArrayIndex].Y;
1398         *OffsetZ = MipTailSlotOffset3DSurface[Slot][ArrayIndex].Z;
1399     }
1400 
1401     GMM_DPF_EXIT;
1402     return;
1403 }
1404 
1405