xref: /aosp_15_r20/external/gmmlib/Source/GmmLib/Resource/GmmResourceInfoCommon.cpp (revision 35ffd701415c9e32e53136d61a677a8d0a8fc4a5)
1 /*==============================================================================
2 Copyright(c) 2017 Intel Corporation
3 
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files(the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and / or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 ============================================================================*/
22 
23 
24 #include "Internal/Common/GmmLibInc.h"
25 
26 /////////////////////////////////////////////////////////////////////////////////////
27 /// Returns indication of whether resource is eligible for 64KB pages or not.
28 /// On Windows, UMD must call this api after GmmResCreate()
29 /// @return     1/0
30 /////////////////////////////////////////////////////////////////////////////////////
Is64KBPageSuitable()31 uint8_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::Is64KBPageSuitable()
32 {
33     bool Ignore64KBPadding = false;
34     //!!!! DO NOT USE GetSizeSurface() as it returns the padded size and not natural size.
35     GMM_GFX_SIZE_T Size = Surf.Size + AuxSurf.Size + AuxSecSurf.Size;
36 
37     __GMM_ASSERT(Size);
38 
39     // All ESM resources and VirtuaPadding are exempt from 64KB paging
40     if(Surf.Flags.Info.ExistingSysMem ||
41        Surf.Flags.Info.XAdapter ||
42        Surf.Flags.Gpu.CameraCapture ||
43        Surf.Flags.Info.KernelModeMapped ||
44        (Surf.Flags.Gpu.S3d && !Surf.Flags.Gpu.S3dDx &&
45         !GetGmmLibContext()->GetSkuTable().FtrDisplayEngineS3d)
46 #if(LHDM)
47        || (Surf.Flags.Info.AllowVirtualPadding &&
48            ExistingSysMem.hParentAllocation)
49 #endif
50        )
51     {
52         Ignore64KBPadding = true;
53     }
54 
55     if(GetGmmLibContext()->GetSkuTable().FtrLocalMemory)
56      {
57         Ignore64KBPadding |= (Surf.Flags.Info.Shared && !Surf.Flags.Info.NotLockable);
58         Ignore64KBPadding |= ((GetGmmLibContext()->GetSkuTable().FtrLocalMemoryAllows4KB) && Surf.Flags.Info.NoOptimizationPadding);
59         Ignore64KBPadding |= ((GetGmmLibContext()->GetSkuTable().FtrLocalMemoryAllows4KB || Surf.Flags.Info.NonLocalOnly) && (((Size * (100 + (GMM_GFX_SIZE_T)GetGmmLibContext()->GetAllowedPaddingFor64KbPagesPercentage())) / 100) < GFX_ALIGN(Size, GMM_KBYTE(64))));
60     }
61     else
62     {
63         // The final padded size cannot be larger then a set percentage of the original size
64         if((Surf.Flags.Info.NoOptimizationPadding && !GFX_IS_ALIGNED(Size, GMM_KBYTE(64))) /*Surface is not 64kb aligned*/ ||
65            (!Surf.Flags.Info.NoOptimizationPadding && (((Size * (100 + (GMM_GFX_SIZE_T)GetGmmLibContext()->GetAllowedPaddingFor64KbPagesPercentage())) / 100) < GFX_ALIGN(Size, GMM_KBYTE(64)))) /*10% padding TBC */)
66         {
67             Ignore64KBPadding |= true;
68         }
69     }
70 
71     // If 64KB paging is enabled pad out the resource to 64KB alignment
72     if(GetGmmLibContext()->GetSkuTable().FtrWddm2_1_64kbPages &&
73        // Ignore the padding for the above VirtualPadding or ESM cases
74        (!Ignore64KBPadding) &&
75        // Resource must be 64KB aligned
76        (GFX_IS_ALIGNED(Surf.Alignment.BaseAlignment, GMM_KBYTE(64)) ||
77         // Or must be aligned to a factor of 64KB
78         (Surf.Alignment.BaseAlignment == GMM_KBYTE(32)) ||
79         (Surf.Alignment.BaseAlignment == GMM_KBYTE(16)) ||
80         (Surf.Alignment.BaseAlignment == GMM_KBYTE(8)) ||
81         (Surf.Alignment.BaseAlignment == GMM_KBYTE(4))))
82     {
83         return 1;
84     }
85 
86     return 0;
87 }
88 
89 /////////////////////////////////////////////////////////////////////////////////////
90 /// Allows clients to "create" any type of resource. This function does not
91 /// allocate any memory for the resource. It just calculates the various parameters
92 /// which are useful for the client and can be queried using other functions.
93 ///
94 /// @param[in]  GmmLib Context: Reference to ::GmmLibContext
95 /// @param[in]  CreateParams: Flags which specify what sort of resource to create
96 ///
97 /// @return     ::GMM_STATUS
98 /////////////////////////////////////////////////////////////////////////////////////
Create(GMM_RESCREATE_PARAMS & CreateParams)99 GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::Create(GMM_RESCREATE_PARAMS &CreateParams)
100 {
101     GMM_STATUS Status = GMM_ERROR;
102     // ToDo: Only Vk is using this Create API directly. Derive the GmmLibCOntext from the ClientContext stored in
103     // ResInfo object.
104     Status = Create(*(reinterpret_cast<GMM_CLIENT_CONTEXT *>(pClientContext)->GetLibContext()), CreateParams);
105 
106     return Status;
107 }
108 
109 /////////////////////////////////////////////////////////////////////////////////////
110 /// Allows clients to "create"  Custom memory layout received from the App as user pointer or DMABUF
111 // This function does not allocate any memory for the resource. It just calculates/ populates the various parameters
112 /// which are useful for the client and can be queried using other functions.
113 ///
114 /// @param[in]  GmmLib Context: Reference to ::GmmLibContext
115 /// @param[in]  CreateParams: Flags which specify what sort of resource to create
116 ///
117 /// @return     ::GMM_STATUS
118 /////////////////////////////////////////////////////////////////////////////////////
CreateCustomRes(Context & GmmLibContext,GMM_RESCREATE_CUSTOM_PARAMS & CreateParams)119 GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::CreateCustomRes(Context &GmmLibContext, GMM_RESCREATE_CUSTOM_PARAMS &CreateParams)
120 {
121     const GMM_PLATFORM_INFO *pPlatform;
122     GMM_STATUS               Status       = GMM_ERROR;
123     GMM_TEXTURE_CALC *       pTextureCalc = NULL;
124     uint32_t                 BitsPerPixel, i;
125 
126 
127     GMM_DPF_ENTER;
128 
129     GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
130     pGmmUmdLibContext = reinterpret_cast<uint64_t>(&GmmLibContext);
131     __GMM_ASSERTPTR(pGmmUmdLibContext, GMM_ERROR);
132 
133     if((CreateParams.Format > GMM_FORMAT_INVALID) &&
134        (CreateParams.Format < GMM_RESOURCE_FORMATS))
135     {
136         BitsPerPixel = GetGmmLibContext()->GetPlatformInfo().FormatTable[CreateParams.Format].Element.BitsPer;
137     }
138     else
139     {
140         GMM_ASSERTDPF(0, "Format Error");
141         Status = GMM_INVALIDPARAM;
142         goto ERROR_CASE;
143     }
144 
145     pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
146     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
147 
148     Surf.Type                    = CreateParams.Type;
149     Surf.Format                  = CreateParams.Format;
150     Surf.BaseWidth               = CreateParams.BaseWidth64;
151     Surf.BaseHeight              = CreateParams.BaseHeight;
152     Surf.Flags                   = CreateParams.Flags;
153     Surf.CachePolicy.Usage       = CreateParams.Usage;
154     Surf.Pitch                   = CreateParams.Pitch;
155     Surf.Size                    = CreateParams.Size;
156     Surf.Alignment.BaseAlignment = CreateParams.BaseAlignment;
157     Surf.MaxLod                  = 1;
158     Surf.ArraySize               = 1;
159     Surf.CpTag                   = CreateParams.CpTag;
160 
161 #if(_DEBUG || _RELEASE_INTERNAL)
162     Surf.Platform = GetGmmLibContext()->GetPlatformInfo().Platform;
163 #endif
164     Surf.BitsPerPixel     = BitsPerPixel;
165     Surf.Alignment.QPitch = (GMM_GLOBAL_GFX_SIZE_T)(Surf.Pitch * Surf.BaseHeight);
166 
167     pTextureCalc->SetTileMode(&Surf);
168 
169     if(GmmIsPlanar(Surf.Format))
170     {
171         pTextureCalc->SetPlanarOffsetInfo(&Surf, CreateParams);
172 
173         if (Surf.ArraySize > 1)
174         {
175             //Surf.OffsetInfo.Plane.ArrayQPitch = Surf.Size;  //Not required as this new interface doesn't support arrayed surfaces.
176         }
177 
178         UpdateUnAlignedParams();
179     }
180 
181     switch(Surf.Type)
182     {
183         case RESOURCE_1D:
184         case RESOURCE_2D:
185         case RESOURCE_PRIMARY:
186         case RESOURCE_SHADOW:
187         case RESOURCE_STAGING:
188         case RESOURCE_GDI:
189         case RESOURCE_NNDI:
190         case RESOURCE_HARDWARE_MBM:
191         case RESOURCE_OVERLAY_INTERMEDIATE_SURFACE:
192         case RESOURCE_IFFS_MAPTOGTT:
193 #if _WIN32
194         case RESOURCE_WGBOX_ENCODE_DISPLAY:
195         case RESOURCE_WGBOX_ENCODE_REFERENCE:
196 #endif
197         {
198 
199         if (Surf.ArraySize > 1)
200         {
201            // Surf.OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
202            // Surf.OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = Surf.Pitch * Surf.BaseHeight;  //Not required as this new interface doesn't support arrayed surfaces.
203         }
204 
205             for(i = 0; i <= Surf.MaxLod; i++)
206             {
207                 Surf.OffsetInfo.Texture2DOffsetInfo.Offset[i] = 0;
208             }
209 
210             break;
211         }
212         default:
213         {
214             GMM_ASSERTDPF(0, "GmmTexAlloc: Unknown surface type!");
215             Status = GMM_INVALIDPARAM;
216             goto ERROR_CASE;
217             ;
218         }
219     };
220 
221     GMM_DPF_EXIT;
222     return GMM_SUCCESS;
223 
224 ERROR_CASE:
225     //Zero out all the members
226     new(this) GmmResourceInfoCommon();
227 
228     GMM_DPF_EXIT;
229     return Status;
230 }
231 
232 #ifndef __GMM_KMD__
233 /////////////////////////////////////////////////////////////////////////////////////
234 /// Allows clients to "create"  Custom memory layout received from the App as user pointer or DMABUF
235 // This function does not allocate any memory for the resource. It just calculates/ populates the various parameters
236 /// which are useful for the client and can be queried using other functions.
237 ///
238 /// @param[in]  GmmLib Context: Reference to ::GmmLibContext
239 /// @param[in]  CreateParams: Flags which specify what sort of resource to create
240 ///
241 /// @return     ::GMM_STATUS
242 /////////////////////////////////////////////////////////////////////////////////////
CreateCustomRes_2(Context & GmmLibContext,GMM_RESCREATE_CUSTOM_PARAMS_2 & CreateParams)243 GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::CreateCustomRes_2(Context &GmmLibContext, GMM_RESCREATE_CUSTOM_PARAMS_2 &CreateParams)
244 {
245     const GMM_PLATFORM_INFO *pPlatform;
246     GMM_STATUS               Status       = GMM_ERROR;
247     GMM_TEXTURE_CALC *       pTextureCalc = NULL;
248     uint32_t                 BitsPerPixel, i;
249 
250 
251     GMM_DPF_ENTER;
252 
253     GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
254     pGmmUmdLibContext = reinterpret_cast<uint64_t>(&GmmLibContext);
255     __GMM_ASSERTPTR(pGmmUmdLibContext, GMM_ERROR);
256 
257 
258     if((CreateParams.Format > GMM_FORMAT_INVALID) &&
259        (CreateParams.Format < GMM_RESOURCE_FORMATS))
260     {
261         BitsPerPixel = GetGmmLibContext()->GetPlatformInfo().FormatTable[CreateParams.Format].Element.BitsPer;
262     }
263     else
264     {
265         GMM_ASSERTDPF(0, "Format Error");
266         Status = GMM_INVALIDPARAM;
267         goto ERROR_CASE;
268     }
269 
270     pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
271     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
272 
273     Surf.Type                    = CreateParams.Type;
274     Surf.Format                  = CreateParams.Format;
275     Surf.BaseWidth               = CreateParams.BaseWidth64;
276     Surf.BaseHeight              = CreateParams.BaseHeight;
277     Surf.Flags                   = CreateParams.Flags;
278     Surf.CachePolicy.Usage       = CreateParams.Usage;
279     Surf.Pitch                   = CreateParams.Pitch;
280     Surf.Size                    = CreateParams.Size;
281     Surf.Alignment.BaseAlignment = CreateParams.BaseAlignment;
282     Surf.MaxLod                  = 1;
283     Surf.ArraySize               = 1;
284     Surf.CpTag                   = CreateParams.CpTag;
285 
286 #if(_DEBUG || _RELEASE_INTERNAL)
287     Surf.Platform = GetGmmLibContext()->GetPlatformInfo().Platform;
288 #endif
289     Surf.BitsPerPixel     = BitsPerPixel;
290     Surf.Alignment.QPitch = (GMM_GLOBAL_GFX_SIZE_T)(Surf.Pitch * Surf.BaseHeight);
291 
292     pTextureCalc->SetTileMode(&Surf);
293 
294     if(GmmIsPlanar(Surf.Format))
295     {
296         pTextureCalc->SetPlanarOffsetInfo_2(&Surf, CreateParams);
297 
298         if(Surf.ArraySize > 1)
299         {
300             //Not required as this new interface doesn't support arrayed surfaces.
301         }
302 
303         UpdateUnAlignedParams();
304     }
305 
306     switch(Surf.Type)
307     {
308         case RESOURCE_1D:
309         case RESOURCE_2D:
310         case RESOURCE_PRIMARY:
311         case RESOURCE_SHADOW:
312         case RESOURCE_STAGING:
313         case RESOURCE_GDI:
314         case RESOURCE_NNDI:
315         case RESOURCE_HARDWARE_MBM:
316         case RESOURCE_OVERLAY_INTERMEDIATE_SURFACE:
317         case RESOURCE_IFFS_MAPTOGTT:
318 #if _WIN32
319         case RESOURCE_WGBOX_ENCODE_DISPLAY:
320         case RESOURCE_WGBOX_ENCODE_REFERENCE:
321 #endif
322         {
323             if(Surf.ArraySize > 1)
324             {
325                 //Not required as this new interface doesn't support arrayed surfaces.
326             }
327 
328             for(i = 0; i <= Surf.MaxLod; i++)
329             {
330                 Surf.OffsetInfo.Texture2DOffsetInfo.Offset[i] = 0;
331             }
332 
333             break;
334         }
335         default:
336         {
337             GMM_ASSERTDPF(0, "GmmTexAlloc: Unknown surface type!");
338             Status = GMM_INVALIDPARAM;
339             goto ERROR_CASE;
340             ;
341         }
342     };
343 
344     if(Surf.Flags.Gpu.UnifiedAuxSurface || Surf.Flags.Gpu.CCS)
345     {
346 
347         if(GetGmmLibContext()->GetSkuTable().FtrLinearCCS)
348         {
349             AuxSurf.Flags.Gpu.__NonMsaaLinearCCS = 1;
350         }
351 
352         AuxSurf.Flags.Info.TiledW  = 0;
353         AuxSurf.Flags.Info.TiledYf = 0;
354         AuxSurf.Flags.Info.TiledX  = 0;
355         AuxSurf.Flags.Info.Linear  = 1;
356         GMM_SET_64KB_TILE(AuxSurf.Flags, 0, GetGmmLibContext());
357         GMM_SET_4KB_TILE(AuxSurf.Flags, 0, GetGmmLibContext());
358 
359         AuxSurf.ArraySize    = 1;
360         AuxSurf.BitsPerPixel = 8;
361 
362         if(GmmIsPlanar(CreateParams.Format) || GmmIsUVPacked(CreateParams.Format))
363         {
364             AuxSurf.OffsetInfo.Plane.X[GMM_PLANE_Y] = CreateParams.AuxSurf.PlaneOffset.X[GMM_PLANE_Y];
365             AuxSurf.OffsetInfo.Plane.Y[GMM_PLANE_Y] = CreateParams.AuxSurf.PlaneOffset.Y[GMM_PLANE_Y];
366             AuxSurf.OffsetInfo.Plane.X[GMM_PLANE_U] = CreateParams.AuxSurf.PlaneOffset.X[GMM_PLANE_U];
367             AuxSurf.OffsetInfo.Plane.Y[GMM_PLANE_U] = CreateParams.AuxSurf.PlaneOffset.Y[GMM_PLANE_U];
368             AuxSurf.OffsetInfo.Plane.X[GMM_PLANE_V] = CreateParams.AuxSurf.PlaneOffset.X[GMM_PLANE_V];
369             AuxSurf.OffsetInfo.Plane.Y[GMM_PLANE_V] = CreateParams.AuxSurf.PlaneOffset.Y[GMM_PLANE_V];
370             AuxSurf.OffsetInfo.Plane.ArrayQPitch    = CreateParams.AuxSurf.Size;
371         }
372 
373         AuxSurf.Size = CreateParams.AuxSurf.Size;
374 
375         AuxSurf.Pitch     = CreateParams.AuxSurf.Pitch;
376         AuxSurf.Type      = RESOURCE_BUFFER;
377         AuxSurf.Alignment = {0};
378 
379         AuxSurf.Alignment.QPitch        = GFX_ULONG_CAST(AuxSurf.Size);
380         AuxSurf.Alignment.BaseAlignment = CreateParams.AuxSurf.BaseAlignment; //TODO: TiledResource?
381         AuxSurf.Size                    = GFX_ALIGN(AuxSurf.Size, PAGE_SIZE); //page-align final size
382 
383         if(AuxSurf.Flags.Gpu.TiledResource)
384         {
385             AuxSurf.Alignment.BaseAlignment = GMM_KBYTE(64);                          //TODO: TiledResource?
386             AuxSurf.Size                    = GFX_ALIGN(AuxSurf.Size, GMM_KBYTE(64)); //page-align final size
387         }
388 
389         //Clear compression request in CCS
390         AuxSurf.Flags.Info.RenderCompressed = 0;
391         AuxSurf.Flags.Info.MediaCompressed  = 0;
392         AuxSurf.Flags.Info.RedecribedPlanes = 0;
393         pTextureCalc->SetTileMode(&AuxSurf);
394         AuxSurf.UnpaddedSize = AuxSurf.Size;
395     }
396     GMM_DPF_EXIT;
397     return GMM_SUCCESS;
398 
399 ERROR_CASE:
400     //Zero out all the members
401     new(this) GmmResourceInfoCommon();
402 
403     GMM_DPF_EXIT;
404     return Status;
405 }
406 #endif
407 
408 /////////////////////////////////////////////////////////////////////////////////////
409 /// Allows clients to "create" any type of resource. This function does not
410 /// allocate any memory for the resource. It just calculates the various parameters
411 /// which are useful for the client and can be queried using other functions.
412 ///
413 /// @param[in]  GmmLib Context: Reference to ::GmmLibContext
414 /// @param[in]  CreateParams: Flags which specify what sort of resource to create
415 ///
416 /// @return     ::GMM_STATUS
417 /////////////////////////////////////////////////////////////////////////////////////
Create(Context & GmmLibContext,GMM_RESCREATE_PARAMS & CreateParams)418 GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::Create(Context &GmmLibContext, GMM_RESCREATE_PARAMS &CreateParams)
419 {
420     const GMM_PLATFORM_INFO *pPlatform;
421     GMM_STATUS               Status       = GMM_ERROR;
422     GMM_TEXTURE_CALC *       pTextureCalc = NULL;
423 
424     GMM_DPF_ENTER;
425 
426     GET_GMM_CLIENT_TYPE(pClientContext, ClientType);
427     pGmmUmdLibContext = reinterpret_cast<uint64_t>(&GmmLibContext);
428     __GMM_ASSERTPTR(pGmmUmdLibContext, GMM_ERROR);
429 
430     if(CreateParams.Flags.Info.ExistingSysMem &&
431        (CreateParams.Flags.Info.TiledW ||
432         CreateParams.Flags.Info.TiledX ||
433         GMM_IS_4KB_TILE(CreateParams.Flags) ||
434         GMM_IS_64KB_TILE(CreateParams.Flags)))
435     {
436         GMM_ASSERTDPF(0, "Tiled System Accelerated Memory not supported.");
437         Status = GMM_INVALIDPARAM;
438         goto ERROR_CASE;
439     }
440 
441     if(!CopyClientParams(CreateParams))
442     {
443         Status = GMM_INVALIDPARAM;
444         goto ERROR_CASE;
445     }
446 
447     pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
448     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
449 
450     if (!pTextureCalc)
451     {
452         Status = GMM_ERROR;
453         GMM_ASSERTDPF(0, "Texture Calculation pointer is NULL.");
454         goto ERROR_CASE;
455     }
456 
457 #if defined(__GMM_KMD__) || !defined(_WIN32)
458     if(!CreateParams.Flags.Info.ExistingSysMem)
459 #else
460     // TiledResource uses a private gfx alloc, which doesn't receive a  WDDM CreateAllocation
461     if(!CreateParams.Flags.Info.ExistingSysMem &&
462        (CreateParams.NoGfxMemory || CreateParams.Flags.Gpu.TiledResource))
463 #endif
464     {
465         if(!ValidateParams())
466         {
467             GMM_ASSERTDPF(0, "Invalid parameter!");
468             Status = GMM_INVALIDPARAM;
469             goto ERROR_CASE;
470         }
471 
472         if(GMM_SUCCESS != pTextureCalc->AllocateTexture(&Surf))
473         {
474             GMM_ASSERTDPF(0, "GmmTexAlloc failed!");
475             goto ERROR_CASE;
476         }
477 
478         if(Surf.Flags.Gpu.UnifiedAuxSurface)
479         {
480             GMM_GFX_SIZE_T TotalSize;
481             uint32_t       Alignment;
482 
483             if(GMM_SUCCESS != pTextureCalc->FillTexCCS(&Surf, (AuxSecSurf.Type != RESOURCE_INVALID ? &AuxSecSurf : &AuxSurf)))
484             {
485                 GMM_ASSERTDPF(0, "GmmTexAlloc failed!");
486                 goto ERROR_CASE;
487             }
488 
489             if(AuxSurf.Size == 0 && AuxSurf.Type != RESOURCE_INVALID && GMM_SUCCESS != pTextureCalc->AllocateTexture(&AuxSurf))
490             {
491                 GMM_ASSERTDPF(0, "GmmTexAlloc failed!");
492                 goto ERROR_CASE;
493             }
494 
495             AuxSurf.UnpaddedSize = AuxSurf.Size;
496 
497             if(Surf.Flags.Gpu.IndirectClearColor ||
498                Surf.Flags.Gpu.ColorDiscard)
499             {
500                 if(GetGmmLibContext()->GetSkuTable().FtrFlatPhysCCS && AuxSurf.Type == RESOURCE_INVALID)
501                 {
502                     //ie only AuxType is CCS, doesn't exist with FlatCCS, enable it for CC
503                     if (!GetGmmLibContext()->GetSkuTable().FtrXe2Compression || (GetGmmLibContext()->GetSkuTable().FtrXe2Compression && (Surf.MSAA.NumSamples > 1)))
504                     {
505                         AuxSurf.Type = Surf.Type;
506                     }
507                 }
508                 if (!Surf.Flags.Gpu.TiledResource)
509                 {
510                     if (!GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
511                     {
512                         AuxSurf.CCSize = PAGE_SIZE; // 128bit Float Value + 32bit RT Native Value + Padding.
513                         AuxSurf.Size += PAGE_SIZE;
514                     }
515                     else
516                     {
517 
518                         if (Surf.MSAA.NumSamples > 1)
519                         {
520                             AuxSurf.UnpaddedSize += PAGE_SIZE;
521                             AuxSurf.Size += PAGE_SIZE;              // Clear Color stored only for MSAA surfaces
522                         }
523                     }
524                 }
525                 else
526                 {
527                     if (!GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
528                     {
529                         AuxSurf.CCSize = GMM_KBYTE(64); // 128bit Float Value + 32bit RT Native Value + Padding.
530                         AuxSurf.Size += GMM_KBYTE(64);
531                     }
532                     else
533                     {
534                         if (Surf.MSAA.NumSamples > 1)
535                         {
536                             AuxSurf.UnpaddedSize += GMM_KBYTE(64);
537                             AuxSurf.Size += GMM_KBYTE(64);              // Clear Color stored only for MSAA surfaces, stored as part of MCS
538                         }
539                     }
540                 }
541             }
542 
543   	    if(Surf.Flags.Gpu.ProceduralTexture)
544             {
545                 //Do not require main surface access either in GPUVA/physical space.
546                 Surf.Size = 0;
547             }
548 
549             TotalSize = Surf.Size + AuxSurf.Size; //Not including AuxSecSurf size, multi-Aux surface isn't supported for displayables
550             Alignment = GFX_ULONG_CAST(Surf.Pitch * pPlatform->TileInfo[Surf.TileMode].LogicalTileHeight);
551 
552             // We need to pad the aux size to the size of the paired surface's tile row (i.e. Pitch * TileHeight) to
553             // ensure the entire surface can be described with a constant pitch (for GGTT aliasing, clean FENCE'ing and
554             // AcquireSwizzlingRange, even though the aux isn't intentionally part of such fencing).
555             if(Surf.Flags.Gpu.FlipChain &&
556                (!__GMM_IS_ALIGN(TotalSize, Alignment)))
557             {
558                 AuxSurf.Size += (GFX_ALIGN_NP2(TotalSize, Alignment) - TotalSize);
559             }
560 
561             if((Surf.Size + AuxSurf.Size + AuxSecSurf.Size) > (GMM_GFX_SIZE_T)(pPlatform->SurfaceMaxSize))
562             {
563                 GMM_ASSERTDPF(0, "Surface too large!");
564                 goto ERROR_CASE;
565             }
566         }
567     }
568 
569     if(Surf.Flags.Info.ExistingSysMem)
570     {
571         Surf.ExistingSysMem.IsGmmAllocated =
572         (CreateParams.pExistingSysMem &&
573          CreateParams.ExistingSysMemSize) ?
574         false :
575         true;
576 
577         if(!Surf.ExistingSysMem.IsGmmAllocated)
578         {
579             Surf.ExistingSysMem.IsPageAligned =
580             (((CreateParams.pExistingSysMem & (PAGE_SIZE - 1)) == 0) &&
581              (((CreateParams.pExistingSysMem + CreateParams.ExistingSysMemSize) & (PAGE_SIZE - 1)) == 0)) ?
582             true :
583             false;
584         }
585 
586         if(!ValidateParams())
587         {
588             GMM_ASSERTDPF(0, "Invalid parameter!");
589             goto ERROR_CASE;
590         }
591 
592         // Get surface Gfx memory size required.
593         if(GMM_SUCCESS != pTextureCalc->AllocateTexture(&Surf))
594         {
595             GMM_ASSERTDPF(0, "GmmTexAlloc failed!");
596             goto ERROR_CASE;
597         }
598 
599         if(CreateParams.pExistingSysMem &&
600            CreateParams.ExistingSysMemSize)
601         {
602             // Client provided own memory and is not assumed to be Gfx aligned
603             ExistingSysMem.IsGmmAllocated = 0;
604 
605             ExistingSysMem.pExistingSysMem = CreateParams.pExistingSysMem;
606             ExistingSysMem.Size            = CreateParams.ExistingSysMemSize;
607 
608             // An upper dword of 0xffffffff is invalid and may mean the address
609             // was sign extended or came from a rogue UMD. In either case
610             // we can truncate the address down to 32 bits prevent attempts
611             // to access an invalid address range.
612             if((ExistingSysMem.pExistingSysMem & (0xffffffff00000000ull)) == (0xffffffff00000000ull))
613             {
614                 ExistingSysMem.pExistingSysMem &= 0xffffffff;
615             }
616 
617             //Align the base address to new ESM requirements.
618             if(!Surf.ExistingSysMem.IsPageAligned)
619             {
620                 if(GMM_SUCCESS != ApplyExistingSysMemRestrictions())
621                 {
622                     GMM_ASSERTDPF(0, "Malloc'ed Sys Mem too small for gfx surface!");
623                     goto ERROR_CASE;
624                 }
625             }
626             else
627             {
628                 ExistingSysMem.pVirtAddress =
629                 ExistingSysMem.pGfxAlignedVirtAddress = CreateParams.pExistingSysMem;
630             }
631 
632             if((ExistingSysMem.pVirtAddress + Surf.Size) >
633                (CreateParams.pExistingSysMem + ExistingSysMem.Size))
634             {
635                 GMM_ASSERTDPF(0, "Malloc'ed Sys Mem too small for gfx surface");
636                 goto ERROR_CASE;
637             }
638         }
639         else
640         {
641             __GMM_BUFFER_TYPE Restrictions = {0};
642 
643             ExistingSysMem.IsGmmAllocated     = 1;
644             Surf.ExistingSysMem.IsPageAligned = 1;
645 
646             // Adjust memory size to compensate for Gfx alignment.
647             pTextureCalc->GetResRestrictions(&Surf, Restrictions);
648             ExistingSysMem.Size = Restrictions.Alignment + Surf.Size;
649 
650             ExistingSysMem.pVirtAddress = (uint64_t)GMM_MALLOC(GFX_ULONG_CAST(ExistingSysMem.Size));
651             if(!ExistingSysMem.pVirtAddress)
652             {
653                 GMM_ASSERTDPF(0, "Failed to allocate System Accelerated Memory.");
654                 goto ERROR_CASE;
655             }
656             else
657             {
658                 ExistingSysMem.pGfxAlignedVirtAddress = (uint64_t)GFX_ALIGN(ExistingSysMem.pVirtAddress, Restrictions.Alignment);
659             }
660         }
661     }
662 
663     if(Is64KBPageSuitable() && GetGmmLibContext()->GetSkuTable().FtrLocalMemory)
664     {
665         // BaseAlignment can be greater than 64KB and needs to be aligned to 64KB
666         Surf.Alignment.BaseAlignment = GFX_MAX(GFX_ALIGN(Surf.Alignment.BaseAlignment, GMM_KBYTE(64)), GMM_KBYTE(64));
667     }
668 
669     GMM_DPF_EXIT;
670     return GMM_SUCCESS;
671 
672 ERROR_CASE:
673     //Zero out all the members
674     new(this) GmmResourceInfoCommon();
675 
676     if(CreateParams.pPreallocatedResInfo)
677     {
678         this->GetResFlags().Info.__PreallocatedResInfo = 1; // Set flag if PreAllocated ResInfo has been set by the Client.
679     }
680 
681     GMM_DPF_EXIT;
682     return Status;
683 }
684 
UpdateUnAlignedParams()685 void GmmLib::GmmResourceInfoCommon::UpdateUnAlignedParams()
686 {
687     uint32_t          YHeight = 0, VHeight = 0, Height = 0;
688     uint32_t          WidthBytesPhysical = GFX_ULONG_CAST(Surf.BaseWidth) * Surf.BitsPerPixel >> 3;
689     GMM_TEXTURE_CALC *pTextureCalc       = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
690 
691     __GMM_ASSERTPTR(((Surf.TileMode < GMM_TILE_MODES) && (Surf.TileMode >= TILE_NONE)), VOIDRETURN);
692     GMM_DPF_ENTER;
693 
694     Height = Surf.BaseHeight;
695 
696     switch(Surf.Format)
697     {
698         case GMM_FORMAT_IMC1: // IMC1 = IMC3 with Swapped U/V
699         case GMM_FORMAT_IMC3:
700         case GMM_FORMAT_MFX_JPEG_YUV420: // Same as IMC3.
701         // YYYYYYYY
702         // YYYYYYYY
703         // YYYYYYYY
704         // YYYYYYYY
705         // UUUU
706         // UUUU
707         // VVVV
708         // VVVV
709         case GMM_FORMAT_MFX_JPEG_YUV422V: // Similar to IMC3 but U/V are full width.
710             // YYYYYYYY
711             // YYYYYYYY
712             // YYYYYYYY
713             // YYYYYYYY
714             // UUUUUUUU
715             // UUUUUUUU
716             // VVVVVVVV
717             // VVVVVVVV
718             {
719                 YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
720 
721                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(Surf.BaseHeight, 2), GMM_IMCx_PLANE_ROW_ALIGNMENT);
722 
723                 break;
724             }
725         case GMM_FORMAT_MFX_JPEG_YUV411R_TYPE: //Similar to IMC3 but U/V are quarther height and full width.
726             //YYYYYYYY
727             //YYYYYYYY
728             //YYYYYYYY
729             //YYYYYYYY
730             //UUUUUUUU
731             //VVVVVVVV
732             {
733                 YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
734 
735                 VHeight = GFX_ALIGN(GFX_CEIL_DIV(Surf.BaseHeight, 4), GMM_IMCx_PLANE_ROW_ALIGNMENT);
736 
737                 break;
738             }
739         case GMM_FORMAT_MFX_JPEG_YUV411: // Similar to IMC3 but U/V are quarter width and full height.
740         // YYYYYYYY
741         // YYYYYYYY
742         // YYYYYYYY
743         // YYYYYYYY
744         // UU
745         // UU
746         // UU
747         // UU
748         // VV
749         // VV
750         // VV
751         // VV
752         case GMM_FORMAT_MFX_JPEG_YUV422H: // Similar to IMC3 but U/V are full height.
753         // YYYYYYYY
754         // YYYYYYYY
755         // YYYYYYYY
756         // YYYYYYYY
757         // UUUU
758         // UUUU
759         // UUUU
760         // UUUU
761         // VVVV
762         // VVVV
763         // VVVV
764         // VVVV
765         case GMM_FORMAT_BGRP:
766         case GMM_FORMAT_RGBP:
767         case GMM_FORMAT_MFX_JPEG_YUV444: // Similar to IMC3 but U/V are full size.
768             // YYYYYYYY
769             // YYYYYYYY
770             // YYYYYYYY
771             // YYYYYYYY
772             // UUUUUUUU
773             // UUUUUUUU
774             // UUUUUUUU
775             // UUUUUUUU
776             // VVVVVVVV
777             // VVVVVVVV
778             // VVVVVVVV
779             // VVVVVVVV
780             {
781                 YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
782 
783                 VHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
784 
785                 break;
786             }
787         case GMM_FORMAT_IMC2: // IMC2 = IMC4 with Swapped U/V
788         case GMM_FORMAT_IMC4:
789         {
790             // YYYYYYYY
791             // YYYYYYYY
792             // YYYYYYYY
793             // YYYYYYYY
794             // UUUUVVVV
795             // UUUUVVVV
796 
797             __GMM_ASSERT((Surf.Pitch & 1) == 0);
798 
799             YHeight = GFX_ALIGN(Surf.BaseHeight, GMM_IMCx_PLANE_ROW_ALIGNMENT);
800 
801             VHeight = GFX_CEIL_DIV(YHeight, 2);
802 
803             break;
804         }
805         case GMM_FORMAT_I420: // I420 = IYUV
806         case GMM_FORMAT_IYUV: // I420/IYUV = YV12 with Swapped U/V
807         case GMM_FORMAT_YV12:
808         case GMM_FORMAT_YVU9:
809         {
810             // YYYYYYYY
811             // YYYYYYYY
812             // YYYYYYYY
813             // YYYYYYYY
814             // VVVVVV..  <-- V and U planes follow the Y plane, as linear
815             // ..UUUUUU      arrays--without respect to pitch.
816 
817             uint32_t YSize, YVSizeRShift, VSize, UOffset;
818             uint32_t YSizeForUVPurposes, YSizeForUVPurposesDimensionalAlignment;
819 
820             YSize = GFX_ULONG_CAST(Surf.Pitch) * Surf.BaseHeight;
821 
822             // YVU9 has one U/V pixel for each 4x4 Y block.
823             // The others have one U/V pixel for each 2x2 Y block.
824 
825             // YVU9 has a Y:V size ratio of 16 (4x4 --> 1).
826             // The others have a ratio of 4 (2x2 --> 1).
827             YVSizeRShift = (Surf.Format != GMM_FORMAT_YVU9) ? 2 : 4;
828 
829             // If a Y plane isn't fully-aligned to its Y-->U/V block size, the
830             // extra/unaligned Y pixels still need corresponding U/V pixels--So
831             // for the purpose of computing the UVSize, we must consider a
832             // dimensionally "rounded-up" YSize. (E.g. a 13x5 YVU9 Y plane would
833             // require 4x2 U/V planes--the same UVSize as a fully-aligned 16x8 Y.)
834             YSizeForUVPurposesDimensionalAlignment = (Surf.Format != GMM_FORMAT_YVU9) ? 2 : 4;
835             YSizeForUVPurposes =
836             GFX_ALIGN(GFX_ULONG_CAST(Surf.Pitch), YSizeForUVPurposesDimensionalAlignment) *
837             GFX_ALIGN(Surf.BaseHeight, YSizeForUVPurposesDimensionalAlignment);
838 
839             VSize = (YSizeForUVPurposes >> YVSizeRShift);
840 
841             YHeight = GFX_CEIL_DIV(YSize + 2 * VSize, WidthBytesPhysical);
842 
843             break;
844         }
845         case GMM_FORMAT_NV12:
846         case GMM_FORMAT_NV21:
847         case GMM_FORMAT_NV11:
848         case GMM_FORMAT_P010:
849         case GMM_FORMAT_P012:
850         case GMM_FORMAT_P016:
851         case GMM_FORMAT_P208:
852         {
853             // YYYYYYYY
854             // YYYYYYYY
855             // YYYYYYYY
856             // YYYYYYYY
857             // [UV-Packing]
858             YHeight = GFX_ALIGN(Height, __GMM_EVEN_ROW);
859 
860             if((Surf.Format == GMM_FORMAT_NV12) ||
861                (Surf.Format == GMM_FORMAT_NV21) ||
862                (Surf.Format == GMM_FORMAT_P010) ||
863                (Surf.Format == GMM_FORMAT_P012) ||
864                (Surf.Format == GMM_FORMAT_P016))
865             {
866                 VHeight = GFX_CEIL_DIV(Height, 2);
867             }
868             else
869             {
870                 VHeight = YHeight; // U/V plane is same as Y
871             }
872 
873             break;
874         }
875         default:
876         {
877             GMM_ASSERTDPF(0, "Unknown Video Format U\n");
878             break;
879         }
880     }
881 
882     pTextureCalc->SetPlaneUnAlignedTexOffsetInfo(&Surf, YHeight, VHeight);
883 
884 }
885 /////////////////////////////////////////////////////////////////////////////////////
886 /// Returns downscaled width for fast clear of given subresource
887 /// @param[in]  uint32_t : MipLevel
888 /// @return     Width
889 /////////////////////////////////////////////////////////////////////////////////////
GetFastClearWidth(uint32_t MipLevel)890 uint64_t GmmLib::GmmResourceInfoCommon::GetFastClearWidth(uint32_t MipLevel)
891 {
892     uint64_t width      = 0;
893     uint64_t mipWidth   = GetMipWidth(MipLevel);
894     uint32_t numSamples = GetNumSamples();
895 
896     GMM_TEXTURE_CALC *pTextureCalc;
897     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
898 
899     if(numSamples == 1)
900     {
901         width = pTextureCalc->ScaleFCRectWidth(&Surf, mipWidth);
902     }
903     else if(numSamples == 2 || numSamples == 4)
904     {
905         if (GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
906         {
907             width = GFX_ALIGN(mipWidth, 64) / 64;
908         }
909         else
910         {
911             width = GFX_ALIGN(mipWidth, 8) / 8;
912         }
913     }
914     else if(numSamples == 8)
915     {
916         if (GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
917         {
918             width = GFX_ALIGN(mipWidth, 16) / 16;
919         }
920         else
921         {
922             width = GFX_ALIGN(mipWidth, 2) / 2;
923         }
924     }
925     else // numSamples == 16
926     {
927         if (GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
928         {
929             width = GFX_ALIGN(mipWidth, 8) / 8;
930         }
931         else
932         {
933             width = mipWidth;
934         }
935     }
936 
937     return width;
938 }
939 
940 
941 /////////////////////////////////////////////////////////////////////////////////////
942 /// Returns downscaled height for fast clear of given subresource
943 /// @param[in]  uint32_t : MipLevel
944 /// @return     height
945 /////////////////////////////////////////////////////////////////////////////////////
GetFastClearHeight(uint32_t MipLevel)946 uint32_t GmmLib::GmmResourceInfoCommon::GetFastClearHeight(uint32_t MipLevel)
947 {
948     uint32_t height     = 0;
949     uint32_t mipHeight  = GetMipHeight(MipLevel);
950     uint32_t numSamples = GetNumSamples();
951 
952     GMM_TEXTURE_CALC *pTextureCalc;
953     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
954 
955     if(numSamples == 1)
956     {
957         height = pTextureCalc->ScaleFCRectHeight(&Surf, mipHeight);
958     }
959     else
960     {
961         if (GetGmmLibContext()->GetSkuTable().FtrXe2Compression)
962         {
963             height = GFX_ALIGN(mipHeight, 4) / 4;
964         }
965         else
966         {
967             height = GFX_ALIGN(mipHeight, 2) / 2;
968         }
969     }
970 
971     return height;
972 }
973 
974 
975 /////////////////////////////////////////////////////////////////////////////////////
976 /// Returns 2D Surface width to be used for fast clear for a given 3D surface
977 /// @param[in]  uint32_t : MipLevel
978 /// @return     height
979 /////////////////////////////////////////////////////////////////////////////////////
Get2DFastClearSurfaceWidthFor3DSurface(uint32_t MipLevel)980 uint64_t GmmLib::GmmResourceInfoCommon::Get2DFastClearSurfaceWidthFor3DSurface(uint32_t MipLevel)
981 {
982     uint64_t width    = 0;
983     uint64_t mipWidth = GetMipWidth(MipLevel);
984 
985     GMM_TEXTURE_CALC *pTextureCalc;
986     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
987     width        = pTextureCalc->Get2DFCSurfaceWidthFor3DSurface(&Surf, mipWidth);
988     return width;
989 }
990 
991 
Get2DFastClearSurfaceHeightFor3DSurface(uint32_t MipLevel)992 uint64_t GmmLib::GmmResourceInfoCommon::Get2DFastClearSurfaceHeightFor3DSurface(uint32_t MipLevel)
993 {
994     uint64_t          height    = 0;
995     uint32_t          mipHeight = GetMipHeight(MipLevel);
996     uint32_t          mipDepth  = GetMipDepth(MipLevel);
997     GMM_TEXTURE_CALC *pTextureCalc;
998 
999     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1000     height       = pTextureCalc->Get2DFCSurfaceHeightFor3DSurface(&Surf, mipHeight, mipDepth);
1001     return height;
1002 }
1003 
1004 /////////////////////////////////////////////////////////////////////////////////////
1005 /// Returns the Platform info.  If Platform has been overriden by the clients, then
1006 /// it returns the overriden Platform Info struct.
1007 /// @return     Reference to the relevent ::GMM_PLATFORM_INFO
1008 /////////////////////////////////////////////////////////////////////////////////////
GetPlatformInfo()1009 const GMM_PLATFORM_INFO &GmmLib::GmmResourceInfoCommon::GetPlatformInfo()
1010 {
1011 #if(defined(__GMM_KMD__) && (_DEBUG || _RELEASE_INTERNAL))
1012     if(GFX_GET_CURRENT_RENDERCORE(Surf.Platform) != GFX_GET_CURRENT_RENDERCORE(((Context *)pGmmKmdLibContext)->GetPlatformInfo().Platform))
1013     {
1014         return ((Context *)pGmmKmdLibContext)->GetOverridePlatformInfo();
1015     }
1016     else
1017     {
1018         return ((Context *)pGmmKmdLibContext)->GetPlatformInfo();
1019     }
1020 #else
1021     return ((Context *)pGmmUmdLibContext)->GetPlatformInfo();
1022 #endif
1023 }
1024 
1025 /////////////////////////////////////////////////////////////////////////////////////
1026 /// Returns width padded to HAlign. Only called for special flags. See asserts in
1027 /// function for which surfaces are supported.
1028 ///
1029 /// @param[in]  MipLevel Mip level for which the width is requested
1030 /// @return     Padded Width
1031 /////////////////////////////////////////////////////////////////////////////////////
GetPaddedWidth(uint32_t MipLevel)1032 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetPaddedWidth(uint32_t MipLevel)
1033 {
1034     GMM_TEXTURE_CALC *pTextureCalc;
1035     uint32_t          AlignedWidth;
1036     GMM_GFX_SIZE_T    MipWidth;
1037     uint32_t          HAlign;
1038 
1039     __GMM_ASSERT(MipLevel <= Surf.MaxLod);
1040 
1041     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1042 
1043     // This shall be called for Depth and Separate Stencil main surface resource
1044     // This shall be called for the Aux surfaces (MCS, CCS and Hiz) too.
1045     // MCS will have Surf.Flags.Gpu.CCS set
1046     // Hiz will have Surf.Flags.Gpu.HiZ set
1047     __GMM_ASSERT(Surf.Flags.Gpu.Depth || Surf.Flags.Gpu.SeparateStencil ||
1048                  Surf.Flags.Gpu.CCS || Surf.Flags.Gpu.HiZ ||
1049                  AuxSurf.Flags.Gpu.__MsaaTileMcs ||
1050                  AuxSurf.Flags.Gpu.CCS || AuxSurf.Flags.Gpu.__NonMsaaTileYCcs);
1051 
1052     MipWidth = pTextureCalc->GmmTexGetMipWidth(&Surf, MipLevel);
1053 
1054     HAlign = Surf.Alignment.HAlign;
1055     if(AuxSurf.Flags.Gpu.CCS && AuxSurf.Flags.Gpu.__NonMsaaTileYCcs)
1056     {
1057         HAlign = AuxSurf.Alignment.HAlign;
1058     }
1059 
1060     AlignedWidth = __GMM_EXPAND_WIDTH(pTextureCalc,
1061                                       GFX_ULONG_CAST(MipWidth),
1062                                       HAlign,
1063                                       &Surf);
1064 
1065     if(Surf.Flags.Gpu.SeparateStencil)
1066     {
1067         if(Surf.Flags.Info.TiledW)
1068         {
1069             AlignedWidth *= 2;
1070         }
1071 
1072         // Reverse MSAA Expansion ////////////////////////////////////////////////
1073         // It might seem strange that we ExpandWidth (with consideration for MSAA)
1074         // only to "reverse" the MSAA portion of the expansion...It's an order-of-
1075         // operations thing--The intention of the reversal isn't to have
1076         // disregarded the original MSAA expansion but to produce a width, that
1077         // when MSAA'ed will match the true physical width (which requires MSAA
1078         // consideration to compute).
1079         switch(Surf.MSAA.NumSamples)
1080         {
1081             case 1:
1082                 break;
1083             case 2: // Same as 4x...
1084             case 4:
1085                 AlignedWidth /= 2;
1086                 break;
1087             case 8: // Same as 16x...
1088             case 16:
1089                 AlignedWidth /= 4;
1090                 break;
1091             default:
1092                 __GMM_ASSERT(0);
1093         }
1094     }
1095 
1096     // CCS Aux surface, Aligned width needs to be scaled based on main surface bpp
1097     if(AuxSurf.Flags.Gpu.CCS && AuxSurf.Flags.Gpu.__NonMsaaTileYCcs)
1098     {
1099         AlignedWidth = pTextureCalc->ScaleTextureWidth(&AuxSurf, AlignedWidth);
1100     }
1101 
1102     return AlignedWidth;
1103 }
1104 
1105 /////////////////////////////////////////////////////////////////////////////////////
1106 /// Returns height padded to VAlign. Only called for special flags. See asserts in
1107 /// function for which surfaces are supported.
1108 ///
1109 /// @param[in]  MipLevel Mip level for which the height is requested
1110 /// @return     Padded height
1111 /////////////////////////////////////////////////////////////////////////////////////
GetPaddedHeight(uint32_t MipLevel)1112 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetPaddedHeight(uint32_t MipLevel)
1113 {
1114     GMM_TEXTURE_CALC *pTextureCalc;
1115     uint32_t          AlignedHeight, MipHeight;
1116     uint32_t          VAlign;
1117 
1118     __GMM_ASSERT(MipLevel <= Surf.MaxLod);
1119 
1120     // See note in GmmResGetPaddedWidth.
1121     __GMM_ASSERT(Surf.Flags.Gpu.Depth || Surf.Flags.Gpu.SeparateStencil ||
1122                  Surf.Flags.Gpu.CCS || Surf.Flags.Gpu.HiZ ||
1123                  AuxSurf.Flags.Gpu.__MsaaTileMcs ||
1124                  AuxSurf.Flags.Gpu.CCS || AuxSurf.Flags.Gpu.__NonMsaaTileYCcs);
1125 
1126     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1127 
1128     MipHeight = pTextureCalc->GmmTexGetMipHeight(&Surf, MipLevel);
1129 
1130     VAlign = Surf.Alignment.VAlign;
1131     if(AuxSurf.Flags.Gpu.CCS && AuxSurf.Flags.Gpu.__NonMsaaTileYCcs)
1132     {
1133         VAlign = AuxSurf.Alignment.VAlign;
1134     }
1135 
1136     AlignedHeight = __GMM_EXPAND_HEIGHT(pTextureCalc,
1137                                         MipHeight,
1138                                         VAlign,
1139                                         &Surf);
1140 
1141     if(Surf.Flags.Gpu.SeparateStencil)
1142     {
1143         if(Surf.Flags.Info.TiledW)
1144         {
1145             AlignedHeight /= 2;
1146         }
1147 
1148         // Reverse MSAA Expansion ////////////////////////////////////////////////
1149         // See note in GmmResGetPaddedWidth.
1150         switch(Surf.MSAA.NumSamples)
1151         {
1152             case 1:
1153                 break;
1154             case 2:
1155                 break; // No height adjustment for 2x...
1156             case 4:    // Same as 8x...
1157             case 8:
1158                 AlignedHeight /= 2;
1159                 break;
1160             case 16:
1161                 AlignedHeight /= 4;
1162                 break;
1163             default:
1164                 __GMM_ASSERT(0);
1165         }
1166     }
1167 
1168     // CCS Aux surface, AlignedHeight needs to be scaled by 16
1169     if(AuxSurf.Flags.Gpu.CCS && AuxSurf.Flags.Gpu.__NonMsaaTileYCcs)
1170     {
1171         AlignedHeight = pTextureCalc->ScaleTextureHeight(&AuxSurf, AlignedHeight);
1172     }
1173 
1174     return AlignedHeight;
1175 }
1176 
1177 /////////////////////////////////////////////////////////////////////////////////////
1178 /// Returns pitch padded to VAlign. Only called for special flags. See asserts in
1179 /// function for which surfaces are supported.
1180 ///
1181 /// @param[in]  MipLevel Mip level for which the pitch is requested
1182 /// @return     Padded pitch
1183 /////////////////////////////////////////////////////////////////////////////////////
GetPaddedPitch(uint32_t MipLevel)1184 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetPaddedPitch(uint32_t MipLevel)
1185 {
1186     uint32_t AlignedWidth;
1187     uint32_t AlignedPitch;
1188     uint32_t BitsPerPixel;
1189 
1190     __GMM_ASSERT(MipLevel <= Surf.MaxLod);
1191 
1192     // See note in GetPaddedWidth.
1193     AlignedWidth = GetPaddedWidth(MipLevel);
1194 
1195     BitsPerPixel = Surf.BitsPerPixel;
1196     if(AuxSurf.Flags.Gpu.CCS && AuxSurf.Flags.Gpu.__NonMsaaTileYCcs)
1197     {
1198         BitsPerPixel = 8; //Aux surface are 8bpp
1199     }
1200 
1201     AlignedPitch = AlignedWidth * BitsPerPixel >> 3;
1202 
1203     return AlignedPitch;
1204 }
1205 
1206 /////////////////////////////////////////////////////////////////////////////////////
1207 /// Returns resource's QPitch.
1208 ///
1209 /// @return     QPitch
1210 /////////////////////////////////////////////////////////////////////////////////////
GetQPitch()1211 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetQPitch()
1212 {
1213     const GMM_PLATFORM_INFO *pPlatform;
1214     uint32_t                 QPitch;
1215 
1216     pPlatform = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
1217 
1218     __GMM_ASSERT(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN8_CORE);
1219     __GMM_ASSERT((Surf.Type != RESOURCE_3D) ||
1220                  (GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE));
1221 
1222     // 2D/CUBE    ==> distance in rows between array slices
1223     // 3D         ==> distance in rows between R-slices
1224     // Compressed ==> one row contains a complete compression block vertically
1225     // HiZ        ==> HZ_PxPerByte * HZ_QPitch
1226     // Stencil    ==> logical, i.e. not halved
1227 
1228     if((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE) &&
1229        GmmIsCompressed(GetGmmLibContext(), Surf.Format))
1230     {
1231         QPitch = Surf.Alignment.QPitch / GetCompressionBlockHeight();
1232 
1233         if((Surf.Type == RESOURCE_3D) && !Surf.Flags.Info.Linear)
1234         {
1235             const GMM_TILE_MODE TileMode = Surf.TileMode;
1236             __GMM_ASSERT(TileMode < GMM_TILE_MODES);
1237             QPitch = GFX_ALIGN(QPitch, pPlatform->TileInfo[TileMode].LogicalTileHeight);
1238         }
1239     }
1240     else if(Surf.Flags.Gpu.HiZ)
1241     {
1242         QPitch = Surf.Alignment.QPitch * pPlatform->HiZPixelsPerByte;
1243     }
1244     else
1245     {
1246         QPitch = Surf.Alignment.QPitch;
1247     }
1248 
1249     return QPitch;
1250 }
1251 
1252 /////////////////////////////////////////////////////////////////////////////////////
1253 /// Returns offset information to a particular mip map or plane.
1254 ///
1255 /// @param[in][out] Has info about which offset client is requesting. Offset is also
1256 ///                 passed back to the client in this parameter.
1257 /// @return         ::GMM_STATUS
1258 /////////////////////////////////////////////////////////////////////////////////////
GetOffset(GMM_REQ_OFFSET_INFO & ReqInfo)1259 GMM_STATUS GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetOffset(GMM_REQ_OFFSET_INFO &ReqInfo)
1260 {
1261     GMM_TEXTURE_CALC *pTextureCalc;
1262 
1263     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1264 
1265     __GMM_ASSERT((pTextureCalc != NULL));
1266 
1267     if(Surf.Flags.Info.RedecribedPlanes)
1268     {
1269         uint8_t RestoreReqStdLayout = ReqInfo.ReqStdLayout ? 1 : 0;
1270 
1271         // Lock and Render offsets do not require additional handling
1272         if(ReqInfo.ReqLock || ReqInfo.ReqRender)
1273         {
1274             ReqInfo.ReqStdLayout = 0;
1275             GmmTexGetMipMapOffset(&Surf, &ReqInfo, GetGmmLibContext());
1276             ReqInfo.ReqStdLayout = RestoreReqStdLayout;
1277         }
1278 
1279         if(ReqInfo.ReqStdLayout)
1280         {
1281             GMM_REQ_OFFSET_INFO TempReqInfo[GMM_MAX_PLANE] = {0};
1282 	    GMM_TEXTURE_INFO    TexInfo[GMM_MAX_PLANE];
1283             uint32_t            Plane, TotalPlanes = GmmLib::Utility::GmmGetNumPlanes(Surf.Format);
1284 
1285             // Caller must specify which plane they need the offset into if not
1286             // getting the whole surface size
1287             if(ReqInfo.Plane >= GMM_MAX_PLANE ||
1288                (ReqInfo.StdLayout.Offset != -1 && !ReqInfo.Plane))
1289             {
1290                 __GMM_ASSERT(0);
1291                 return GMM_ERROR;
1292             }
1293 
1294             TempReqInfo[GMM_PLANE_Y]         = *&ReqInfo;
1295             TempReqInfo[GMM_PLANE_Y].Plane   = GMM_NO_PLANE;
1296             TempReqInfo[GMM_PLANE_Y].ReqLock = TempReqInfo[GMM_PLANE_Y].ReqRender = 0;
1297 
1298             TempReqInfo[GMM_PLANE_V] = TempReqInfo[GMM_PLANE_U] = TempReqInfo[GMM_PLANE_Y];
1299 
1300 	    pTextureCalc->GetRedescribedPlaneParams(&Surf, GMM_PLANE_Y, &TexInfo[GMM_PLANE_Y]);
1301             pTextureCalc->GetRedescribedPlaneParams(&Surf, GMM_PLANE_U, &TexInfo[GMM_PLANE_U]);
1302             pTextureCalc->GetRedescribedPlaneParams(&Surf, GMM_PLANE_V, &TexInfo[GMM_PLANE_V]);
1303 
1304             if(GMM_SUCCESS != GmmTexGetMipMapOffset(&TexInfo[GMM_PLANE_Y], &TempReqInfo[GMM_PLANE_Y], GetGmmLibContext()) ||
1305                GMM_SUCCESS != GmmTexGetMipMapOffset(&TexInfo[GMM_PLANE_U], &TempReqInfo[GMM_PLANE_U], GetGmmLibContext()) ||
1306                GMM_SUCCESS != GmmTexGetMipMapOffset(&TexInfo[GMM_PLANE_V], &TempReqInfo[GMM_PLANE_V], GetGmmLibContext()))
1307 	    {
1308     		    __GMM_ASSERT(0);
1309                 return GMM_ERROR;
1310             }
1311 
1312             ReqInfo.StdLayout.TileDepthPitch = TempReqInfo[ReqInfo.Plane].StdLayout.TileDepthPitch;
1313             ReqInfo.StdLayout.TileRowPitch   = TempReqInfo[ReqInfo.Plane].StdLayout.TileRowPitch;
1314 
1315             if(ReqInfo.StdLayout.Offset == -1)
1316             {
1317                 // Special request to get the StdLayout size
1318                 ReqInfo.StdLayout.Offset = TempReqInfo[ReqInfo.Plane].StdLayout.Offset;
1319 
1320                 if(!ReqInfo.Plane)
1321                 {
1322                     for(Plane = GMM_PLANE_Y; Plane <= TotalPlanes; Plane++)
1323                     {
1324                         ReqInfo.StdLayout.Offset += TempReqInfo[Plane].StdLayout.Offset;
1325                     }
1326                 }
1327             }
1328             else
1329             {
1330                 ReqInfo.StdLayout.Offset = TempReqInfo[ReqInfo.Plane].StdLayout.Offset;
1331 
1332                 for(Plane = GMM_PLANE_Y; Plane < (uint32_t)ReqInfo.Plane; Plane++)
1333                 {
1334                     // Find the size of the previous planes and add it to the offset
1335                     TempReqInfo[Plane].StdLayout.Offset = -1;
1336 
1337                     if(GMM_SUCCESS != GmmTexGetMipMapOffset(&TexInfo[Plane], &TempReqInfo[Plane], GetGmmLibContext()))
1338                     {
1339 
1340                         __GMM_ASSERT(0);
1341                         return GMM_ERROR;
1342                     }
1343 
1344                     ReqInfo.StdLayout.Offset += TempReqInfo[Plane].StdLayout.Offset;
1345                 }
1346             }
1347         }
1348 
1349         return GMM_SUCCESS;
1350     }
1351     else
1352     {
1353         return GmmTexGetMipMapOffset(&Surf, &ReqInfo, GetGmmLibContext());
1354     }
1355 }
1356 
1357 /////////////////////////////////////////////////////////////////////////////////////
1358 /// Performs a CPU BLT between a specified GPU resource and a system memory surface,
1359 /// as defined by the GMM_RES_COPY_BLT descriptor.
1360 ///
1361 /// @param[in]  pBlt: Describes the blit operation. See ::GMM_RES_COPY_BLT for more info.
1362 /// @return     1 if succeeded, 0 otherwise
1363 /////////////////////////////////////////////////////////////////////////////////////
CpuBlt(GMM_RES_COPY_BLT * pBlt)1364 uint8_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::CpuBlt(GMM_RES_COPY_BLT *pBlt)
1365 {
1366 #define REQUIRE(e)       \
1367     if(!(e))             \
1368     {                    \
1369         __GMM_ASSERT(0); \
1370         Success = 0;     \
1371         goto EXIT;       \
1372     }
1373 
1374     const GMM_PLATFORM_INFO *pPlatform;
1375     uint8_t                  Success = 1;
1376     GMM_TEXTURE_INFO *       pTexInfo;
1377     GMM_TEXTURE_CALC *       pTextureCalc;
1378     GMM_TEXTURE_INFO         RedescribedPlaneInfo;
1379 
1380     __GMM_ASSERTPTR(pBlt, 0);
1381 
1382     pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
1383     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1384 
1385     __GMM_ASSERT(
1386     Surf.Type == RESOURCE_1D ||
1387     Surf.Type == RESOURCE_2D ||
1388     Surf.Type == RESOURCE_PRIMARY ||
1389     Surf.Type == RESOURCE_CUBE ||
1390     Surf.Type == RESOURCE_3D);
1391     __GMM_ASSERT(pBlt->Gpu.MipLevel <= Surf.MaxLod);
1392     __GMM_ASSERT(Surf.MSAA.NumSamples <= 1);                          // Supported by CpuSwizzleBlt--but not yet this function.
1393     __GMM_ASSERT(!Surf.Flags.Gpu.Depth || Surf.MSAA.NumSamples <= 1); // MSAA depth currently ends up with a few exchange swizzles--CpuSwizzleBlt could support with expanded XOR'ing, but probably no use case.
1394     __GMM_ASSERT(!(
1395     pBlt->Blt.Upload &&
1396     Surf.Flags.Gpu.Depth &&
1397     (Surf.BitsPerPixel == 32) &&
1398     (pBlt->Sys.PixelPitch == 4) &&
1399     (pBlt->Blt.BytesPerPixel == 3))); // When uploading D24 data from D24S8 to D24X8, no harm in copying S8 to X8 and upload will then be faster.
1400 
1401     pTexInfo = &(Surf);
1402 
1403     // YUV Planar surface
1404     if(pTextureCalc->IsTileAlignedPlanes(pTexInfo) && GmmIsPlanar(Surf.Format))
1405     {
1406         uint32_t PlaneId = GMM_NO_PLANE;
1407 
1408 	pTextureCalc->GetPlaneIdForCpuBlt(pTexInfo, pBlt, &PlaneId);
1409 
1410 	if(PlaneId == GMM_MAX_PLANE)
1411         {
1412             // TODO BLT rect should not overlap between planes.
1413             {
1414                 // __GMM_ASSERT(0); // decide later, for now blt it
1415                 //return 0;
1416             }
1417 
1418             // BLT monolithic surface per plane and remove padding due to tiling.
1419             for(PlaneId = GMM_PLANE_Y; PlaneId <= pTextureCalc->GetNumberOfPlanes(pTexInfo); PlaneId++)
1420             {
1421                 pTextureCalc->GetBltInfoPerPlane(pTexInfo, pBlt, PlaneId);
1422                 CpuBlt(pBlt);
1423             }
1424         }
1425         // else  continue below
1426     }
1427 
1428     // UV packed planar surfaces will have different tiling geometries for the
1429     // Y and UV planes. Blts cannot span across the tiling boundaries and we
1430     // must select the proper mode for each plane. Non-UV packed formats will
1431     // have a constant tiling mode, and so do not have the same limits
1432     if(Surf.Flags.Info.RedecribedPlanes &&
1433        GmmIsUVPacked(Surf.Format))
1434     {
1435         if(!((pBlt->Gpu.OffsetY >= pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U]) ||
1436              ((pBlt->Gpu.OffsetY + pBlt->Blt.Height) <= pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U])))
1437         {
1438             __GMM_ASSERT(0);
1439             return false;
1440         }
1441 
1442         if(pBlt->Gpu.OffsetY < pTexInfo->OffsetInfo.Plane.Y[GMM_PLANE_U])
1443         {
1444 	    pTextureCalc->GetRedescribedPlaneParams(pTexInfo, GMM_PLANE_Y, &RedescribedPlaneInfo);
1445             // Y Plane
1446             pTexInfo = &RedescribedPlaneInfo;
1447         }
1448         else
1449         {
1450             // UV Plane
1451 	    pTextureCalc->GetRedescribedPlaneParams(pTexInfo, GMM_PLANE_U, &RedescribedPlaneInfo);
1452             pTexInfo = &RedescribedPlaneInfo;
1453         }
1454     }
1455 
1456     if(pBlt->Blt.Slices > 1)
1457     {
1458         GMM_RES_COPY_BLT SliceBlt = *pBlt;
1459         uint32_t         Slice;
1460 
1461         SliceBlt.Blt.Slices = 1;
1462         for(Slice = pBlt->Gpu.Slice;
1463             Slice < (pBlt->Gpu.Slice + pBlt->Blt.Slices);
1464             Slice++)
1465         {
1466             SliceBlt.Gpu.Slice      = Slice;
1467             SliceBlt.Sys.pData      = (void *)((char *)pBlt->Sys.pData + (Slice - pBlt->Gpu.Slice) * pBlt->Sys.SlicePitch);
1468             SliceBlt.Sys.BufferSize = pBlt->Sys.BufferSize - GFX_ULONG_CAST((char *)SliceBlt.Sys.pData - (char *)pBlt->Sys.pData);
1469             CpuBlt(&SliceBlt);
1470         }
1471     }
1472     else // Single Subresource...
1473     {
1474         uint32_t            ResPixelPitch = pTexInfo->BitsPerPixel / CHAR_BIT;
1475         uint32_t            BlockWidth, BlockHeight, BlockDepth;
1476         uint32_t            __CopyWidthBytes, __CopyHeight, __OffsetXBytes, __OffsetY;
1477         GMM_REQ_OFFSET_INFO GetOffset = {0};
1478 
1479         pTextureCalc->GetCompressionBlockDimensions(pTexInfo->Format, &BlockWidth, &BlockHeight, &BlockDepth);
1480 
1481 #if(LHDM)
1482         if(pTexInfo->MsFormat == D3DDDIFMT_G8R8_G8B8 ||
1483            pTexInfo->MsFormat == D3DDDIFMT_R8G8_B8G8)
1484         {
1485             BlockWidth    = 2;
1486             ResPixelPitch = 4;
1487         }
1488 #endif
1489 
1490         { // __CopyWidthBytes...
1491             uint32_t Width;
1492 
1493             if(!pBlt->Blt.Width) // i.e. "Full Width"
1494             {
1495                 __GMM_ASSERT(!GmmIsPlanar(pTexInfo->Format)); // Caller must set Blt.Width--GMM "auto-size on zero" not supported with planars since multiple interpretations would confuse more than help.
1496 
1497                 Width = GFX_ULONG_CAST(pTextureCalc->GmmTexGetMipWidth(pTexInfo, pBlt->Gpu.MipLevel));
1498 
1499                 __GMM_ASSERT(Width >= pBlt->Gpu.OffsetX);
1500                 Width -= pBlt->Gpu.OffsetX;
1501                 __GMM_ASSERT(Width);
1502             }
1503             else
1504             {
1505                 Width = pBlt->Blt.Width;
1506             }
1507 
1508             if(((pBlt->Sys.PixelPitch == 0) ||
1509                 (pBlt->Sys.PixelPitch == ResPixelPitch)) &&
1510                ((pBlt->Blt.BytesPerPixel == 0) ||
1511                 (pBlt->Blt.BytesPerPixel == ResPixelPitch)))
1512             {
1513                 // Full-Pixel BLT...
1514                 __CopyWidthBytes =
1515                 GFX_CEIL_DIV(Width, BlockWidth) * ResPixelPitch;
1516             }
1517             else // Partial-Pixel BLT...
1518             {
1519                 __GMM_ASSERT(BlockWidth == 1); // No partial-pixel support for block-compressed formats.
1520 
1521                 // When copying between surfaces with different pixel pitches,
1522                 // specify CopyWidthBytes in terms of unswizzled surface
1523                 // (convenient convention used by CpuSwizzleBlt).
1524                 __CopyWidthBytes =
1525                 Width *
1526                 (pBlt->Sys.PixelPitch ?
1527                  pBlt->Sys.PixelPitch :
1528                  ResPixelPitch);
1529             }
1530         }
1531 
1532         {                         // __CopyHeight...
1533             if(!pBlt->Blt.Height) // i.e. "Full Height"
1534             {
1535                 __GMM_ASSERT(!GmmIsPlanar(pTexInfo->Format)); // Caller must set Blt.Height--GMM "auto-size on zero" not supported with planars since multiple interpretations would confuse more than help.
1536 
1537                 __CopyHeight = pTextureCalc->GmmTexGetMipHeight(pTexInfo, pBlt->Gpu.MipLevel);
1538                 __GMM_ASSERT(__CopyHeight >= pBlt->Gpu.OffsetY);
1539                 __CopyHeight -= pBlt->Gpu.OffsetY;
1540                 __GMM_ASSERT(__CopyHeight);
1541             }
1542             else
1543             {
1544                 __CopyHeight = pBlt->Blt.Height;
1545             }
1546 
1547             __CopyHeight = GFX_CEIL_DIV(__CopyHeight, BlockHeight);
1548         }
1549 
1550         __GMM_ASSERT((pBlt->Gpu.OffsetX % BlockWidth) == 0);
1551         __OffsetXBytes = (pBlt->Gpu.OffsetX / BlockWidth) * ResPixelPitch + pBlt->Gpu.OffsetSubpixel;
1552 
1553         __GMM_ASSERT((pBlt->Gpu.OffsetY % BlockHeight) == 0);
1554         __OffsetY = (pBlt->Gpu.OffsetY / BlockHeight);
1555 
1556         { // Get pResData Offsets to this subresource...
1557             GetOffset.ReqLock      = pTexInfo->Flags.Info.Linear;
1558             GetOffset.ReqStdLayout = !GetOffset.ReqLock && pTexInfo->Flags.Info.StdSwizzle;
1559             GetOffset.ReqRender    = !GetOffset.ReqLock && !GetOffset.ReqStdLayout;
1560             GetOffset.MipLevel     = pBlt->Gpu.MipLevel;
1561             switch(pTexInfo->Type)
1562             {
1563                 case RESOURCE_1D:
1564                 case RESOURCE_2D:
1565                 case RESOURCE_PRIMARY:
1566                 {
1567                     GetOffset.ArrayIndex = pBlt->Gpu.Slice;
1568                     break;
1569                 }
1570                 case RESOURCE_CUBE:
1571                 {
1572                     GetOffset.ArrayIndex = pBlt->Gpu.Slice / 6;
1573                     GetOffset.CubeFace   = (GMM_CUBE_FACE_ENUM)(pBlt->Gpu.Slice % 6);
1574                     break;
1575                 }
1576                 case RESOURCE_3D:
1577                 {
1578                     GetOffset.Slice = (GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf) ?
1579                                       (pBlt->Gpu.Slice / pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth) :
1580                                       pBlt->Gpu.Slice;
1581                     break;
1582                 }
1583                 default:
1584                     __GMM_ASSERT(0);
1585             }
1586 
1587             REQUIRE(this->GetOffset(GetOffset) == GMM_SUCCESS);
1588         }
1589 
1590         if(pTexInfo->Flags.Info.Linear)
1591         {
1592             char *   pDest, *pSrc;
1593             uint32_t DestPitch, SrcPitch;
1594             uint32_t y;
1595 
1596             __GMM_ASSERT( // Linear-to-linear subpixel BLT unexpected--Not implemented.
1597             (!pBlt->Sys.PixelPitch || (pBlt->Sys.PixelPitch == ResPixelPitch)) &&
1598             (!pBlt->Blt.BytesPerPixel || (pBlt->Blt.BytesPerPixel == ResPixelPitch)));
1599 
1600             if(pBlt->Blt.Upload)
1601             {
1602                 pDest     = (char *)pBlt->Gpu.pData;
1603                 DestPitch = GFX_ULONG_CAST(pTexInfo->Pitch);
1604 
1605                 pSrc     = (char *)pBlt->Sys.pData;
1606                 SrcPitch = pBlt->Sys.RowPitch;
1607             }
1608             else
1609             {
1610                 pDest     = (char *)pBlt->Sys.pData;
1611                 DestPitch = pBlt->Sys.RowPitch;
1612 
1613                 pSrc     = (char *)pBlt->Gpu.pData;
1614                 SrcPitch = GFX_ULONG_CAST(pTexInfo->Pitch);
1615             }
1616 
1617             __GMM_ASSERT(GetOffset.Lock.Offset < pTexInfo->Size);
1618             pDest += GetOffset.Lock.Offset + (__OffsetY * DestPitch + __OffsetXBytes);
1619 
1620             for(y = 0; y < __CopyHeight; y++)
1621             {
1622 // Memcpy per row isn't optimal, but doubt this linear-to-linear path matters.
1623 
1624 #if _WIN32
1625 #ifdef __GMM_KMD__
1626                 GFX_MEMCPY_S
1627 #else
1628                 memcpy_s
1629 #endif
1630                 (pDest, __CopyWidthBytes, pSrc, __CopyWidthBytes);
1631 #else
1632                 memcpy(pDest, pSrc, __CopyWidthBytes);
1633 #endif
1634                 pDest += DestPitch;
1635                 pSrc += SrcPitch;
1636             }
1637         }
1638         else // Swizzled BLT...
1639         {
1640             CPU_SWIZZLE_BLT_SURFACE LinearSurface = {0}, SwizzledSurface;
1641             uint32_t                ZOffset       = 0;
1642 
1643             __GMM_ASSERT(GetOffset.Render.Offset64 < pTexInfo->Size);
1644 
1645             ZOffset = (pTexInfo->Type == RESOURCE_3D &&
1646                        (GMM_IS_64KB_TILE(pTexInfo->Flags) || pTexInfo->Flags.Info.TiledYf)) ?
1647                       (pBlt->Gpu.Slice % pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth) :
1648                       0;
1649 
1650             if(pTexInfo->Flags.Info.StdSwizzle == 1)
1651             {
1652                 SwizzledSurface.pBase   = (char *)pBlt->Gpu.pData + GFX_ULONG_CAST(GetOffset.StdLayout.Offset);
1653                 SwizzledSurface.OffsetX = __OffsetXBytes;
1654                 SwizzledSurface.OffsetY = __OffsetY;
1655                 SwizzledSurface.OffsetZ = ZOffset;
1656 
1657                 uint32_t MipWidth  = GFX_ULONG_CAST(pTextureCalc->GmmTexGetMipWidth(pTexInfo, pBlt->Gpu.MipLevel));
1658                 uint32_t MipHeight = pTextureCalc->GmmTexGetMipHeight(pTexInfo, pBlt->Gpu.MipLevel);
1659 
1660                 pTextureCalc->AlignTexHeightWidth(pTexInfo, &MipHeight, &MipWidth);
1661                 SwizzledSurface.Height = MipHeight;
1662                 SwizzledSurface.Pitch  = MipWidth * ResPixelPitch;
1663             }
1664             else
1665             {
1666                 SwizzledSurface.pBase   = (char *)pBlt->Gpu.pData + GFX_ULONG_CAST(GetOffset.Render.Offset64);
1667                 SwizzledSurface.Pitch   = GFX_ULONG_CAST(pTexInfo->Pitch);
1668                 SwizzledSurface.OffsetX = GetOffset.Render.XOffset + __OffsetXBytes;
1669                 SwizzledSurface.OffsetY = GetOffset.Render.YOffset + __OffsetY;
1670                 SwizzledSurface.OffsetZ = GetOffset.Render.ZOffset + ZOffset;
1671                 SwizzledSurface.Height  = GFX_ULONG_CAST(pTexInfo->Size / pTexInfo->Pitch);
1672             }
1673 
1674             SwizzledSurface.Element.Pitch = ResPixelPitch;
1675 
1676             LinearSurface.pBase = pBlt->Sys.pData;
1677             LinearSurface.Pitch = pBlt->Sys.RowPitch;
1678             LinearSurface.Height =
1679             pBlt->Sys.BufferSize /
1680             (pBlt->Sys.RowPitch ?
1681              pBlt->Sys.RowPitch :
1682              pBlt->Sys.BufferSize);
1683             LinearSurface.Element.Pitch =
1684             pBlt->Sys.PixelPitch ?
1685             pBlt->Sys.PixelPitch :
1686             ResPixelPitch;
1687             LinearSurface.Element.Size =
1688             SwizzledSurface.Element.Size =
1689             pBlt->Blt.BytesPerPixel ?
1690             pBlt->Blt.BytesPerPixel :
1691             ResPixelPitch;
1692 
1693             SwizzledSurface.pSwizzle = NULL;
1694 
1695             if(pTexInfo->Flags.Info.TiledW)
1696             {
1697                 SwizzledSurface.pSwizzle = &INTEL_TILE_W;
1698 
1699                 // Correct for GMM's 2x Pitch handling of stencil...
1700                 // (Unlike the HW, CpuSwizzleBlt handles TileW as a natural,
1701                 // 64x64=4KB tile, so the pre-Gen10 "double-pitch/half-height"
1702                 // kludging to TileY shape must be reversed.)
1703                 __GMM_ASSERT((SwizzledSurface.Pitch % 2) == 0);
1704                 SwizzledSurface.Pitch /= 2;
1705                 SwizzledSurface.Height *= 2;
1706             }
1707             else if(GMM_IS_4KB_TILE(pTexInfo->Flags) &&
1708                     !(pTexInfo->Flags.Info.TiledYf ||
1709                       GMM_IS_64KB_TILE(pTexInfo->Flags)))
1710             {
1711                 if(GetGmmLibContext()->GetSkuTable().FtrTileY)
1712                  {
1713                     SwizzledSurface.pSwizzle = &INTEL_TILE_Y;
1714                 }
1715                 else
1716                 {
1717                     SwizzledSurface.pSwizzle = &INTEL_TILE_4;
1718                 }
1719             }
1720             else if(pTexInfo->Flags.Info.TiledX)
1721             {
1722                 SwizzledSurface.pSwizzle = &INTEL_TILE_X;
1723             }
1724             else // Yf/s...
1725             {
1726 // clang-format off
1727                 #define NA
1728 
1729                 #define CASE(Layout, Tile, msaa, xD, bpe)                               \
1730                     case bpe:                                                           \
1731                         SwizzledSurface.pSwizzle = &Layout##_##Tile##_##msaa##xD##bpe;  \
1732                         break
1733 
1734                 #define SWITCH_BPP(Layout, Tile, msaa, xD)    \
1735                     switch(pTexInfo->BitsPerPixel)            \
1736                     {                                         \
1737                         CASE(Layout, Tile, msaa, xD, 8);      \
1738                         CASE(Layout, Tile, msaa, xD, 16);     \
1739                         CASE(Layout, Tile, msaa, xD, 32);     \
1740                         CASE(Layout, Tile, msaa, xD, 64);     \
1741                         CASE(Layout, Tile, msaa, xD, 128);    \
1742                     }
1743 
1744                 #define SWITCH_MSAA_TILE64(Layout, Tile, xD)     \
1745                 {\
1746                     switch(pTexInfo->MSAA.NumSamples)           \
1747                     {                                           \
1748                         case 0:                                 \
1749                             SWITCH_BPP(Layout, TILE_64, , xD);    \
1750                             break;                              \
1751                         case 1:                                 \
1752                             SWITCH_BPP(Layout, TILE_64, , xD);    \
1753                             break;                              \
1754                         case 2:                                 \
1755                             if(GetGmmLibContext()->GetSkuTable().FtrXe2PlusTiling)\
1756                             { \
1757                                 SWITCH_BPP(Layout, TILE_64_V2, MSAA2_, xD); \
1758                             }\
1759                             else\
1760                             { \
1761                                 SWITCH_BPP(Layout, TILE_64, MSAA2_, xD); \
1762                             } \
1763                             break;                              \
1764                         case 4:                                 \
1765                             if(GetGmmLibContext()->GetSkuTable().FtrXe2PlusTiling)\
1766                             { \
1767                                 SWITCH_BPP(Layout, TILE_64_V2, MSAA4_, xD); \
1768                             }\
1769                             else\
1770                             { \
1771                                 SWITCH_BPP(Layout, TILE_64, MSAA_, xD); \
1772                             } \
1773                             break; \
1774                         case 8:                                 \
1775                             if(GetGmmLibContext()->GetSkuTable().FtrXe2PlusTiling)\
1776                             { \
1777                                 SWITCH_BPP(Layout, TILE_64_V2, MSAA8_, xD); \
1778                             }\
1779                             else\
1780                             { \
1781                                 SWITCH_BPP(Layout, TILE_64, MSAA_, xD); \
1782                             } \
1783                             break; \
1784                         case 16:                                \
1785                             if(GetGmmLibContext()->GetSkuTable().FtrXe2PlusTiling)\
1786                             { \
1787                                 SWITCH_BPP(Layout, TILE_64_V2, MSAA16_, xD); \
1788                             }\
1789                             else\
1790                             { \
1791                                 SWITCH_BPP(Layout, TILE_64, MSAA_, xD); \
1792                             } \
1793                             break; \
1794                     }                                           \
1795                 } \
1796 
1797                 #define SWITCH_MSAA(Layout, Tile, xD)           \
1798                 {\
1799                     switch(pTexInfo->MSAA.NumSamples)           \
1800                     {                                           \
1801                         case 0:                                 \
1802                             SWITCH_BPP(Layout, Tile, , xD);     \
1803                             break;                              \
1804                         case 1:                                 \
1805                             SWITCH_BPP(Layout, Tile, , xD);     \
1806                             break;                              \
1807                         case 2:                                 \
1808                             SWITCH_BPP(Layout, Tile, MSAA2_, xD);  \
1809                             break;                              \
1810                         case 4:                                 \
1811                             SWITCH_BPP(Layout, Tile, MSAA4_, xD);  \
1812                             break;                              \
1813                         case 8:                                 \
1814                             SWITCH_BPP(Layout, Tile, MSAA8_, xD);     \
1815                             break;                              \
1816                         case 16:                                \
1817                             SWITCH_BPP(Layout, Tile, MSAA16_, xD);    \
1818                             break;                              \
1819                     }\
1820                 }
1821                 // clang-format on
1822 
1823                 if(pTexInfo->Type == RESOURCE_3D)
1824                 {
1825                     if(pTexInfo->Flags.Info.TiledYf)
1826                     {
1827                         SWITCH_BPP(INTEL, TILE_YF, , 3D_);
1828                     }
1829                     else if(GMM_IS_64KB_TILE(pTexInfo->Flags))
1830                     {
1831                         if(GetGmmLibContext()->GetSkuTable().FtrTileY)
1832                         {
1833                             SWITCH_BPP(INTEL, TILE_YS, , 3D_);
1834                         }
1835                         else
1836                         {
1837                             if (GetGmmLibContext()->GetSkuTable().FtrXe2PlusTiling)
1838                             {
1839                                 SWITCH_BPP(INTEL, TILE_64_V2, , 3D_);
1840                             }
1841                             else
1842                             {
1843                                 SWITCH_BPP(INTEL, TILE_64, , 3D_);
1844                             }
1845                         }
1846                     }
1847                 }
1848                 else // 2D/Cube...
1849                 {
1850                     if(pTexInfo->Flags.Info.TiledYf)
1851                     {
1852                         SWITCH_MSAA(INTEL, TILE_YF, );
1853                     }
1854                     else if(GMM_IS_64KB_TILE(pTexInfo->Flags))
1855                     {
1856                         if(GetGmmLibContext()->GetSkuTable().FtrTileY)
1857                         {
1858                             SWITCH_MSAA(INTEL, TILE_YS, );
1859                         }
1860                         else
1861                         {
1862                             SWITCH_MSAA_TILE64(INTEL, TILE_64, );
1863                         }
1864                     }
1865                 }
1866             }
1867             __GMM_ASSERT(SwizzledSurface.pSwizzle);
1868 
1869             if(pBlt->Blt.Upload)
1870             {
1871                 CpuSwizzleBlt(&SwizzledSurface, &LinearSurface, __CopyWidthBytes, __CopyHeight);
1872             }
1873             else
1874             {
1875                 CpuSwizzleBlt(&LinearSurface, &SwizzledSurface, __CopyWidthBytes, __CopyHeight);
1876             }
1877         }
1878     }
1879 
1880 EXIT:
1881 
1882     return Success;
1883 }
1884 
1885 /////////////////////////////////////////////////////////////////////////////////////
1886 /// Helper function that helps UMDs map in the surface in a layout that
1887 /// our HW understands. Clients call this function in a loop until it
1888 /// returns failure. Clients will get back information in pMapping->Span,
1889 /// which they can use to map Span.Size bytes to Span.VirtualOffset gfx
1890 /// address with Span.PhysicalOffset physical page.
1891 ///
1892 /// @param[in]  pMapping: Clients call the function with initially zero'd out GMM_GET_MAPPING.
1893 /// @return      1 if more span descriptors to report, 0 if all mapping is done
1894 /////////////////////////////////////////////////////////////////////////////////////
GetMappingSpanDesc(GMM_GET_MAPPING * pMapping)1895 uint8_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetMappingSpanDesc(GMM_GET_MAPPING *pMapping)
1896 {
1897     const GMM_PLATFORM_INFO *pPlatform;
1898     uint8_t                  WasFinalSpan = 0;
1899     GMM_TEXTURE_INFO *       pTexInfo;
1900     GMM_TEXTURE_CALC *       pTextureCalc;
1901     GMM_TEXTURE_INFO         RedescribedPlaneInfo;
1902     bool Aux = false;
1903 
1904     __GMM_ASSERT(Surf.Flags.Info.StdSwizzle);
1905 
1906     pPlatform    = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
1907     pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
1908 
1909     __GMM_ASSERT(pTextureCalc != NULL);
1910     pTexInfo = &Surf;
1911 
1912     if((pMapping->Type == GMM_MAPPING_YUVPLANAR_AUX || pMapping->Type == GMM_MAPPING_YUVPLANAR) && GmmIsPlanar(Surf.Format))
1913     {
1914         uint32_t            Plane;
1915         GMM_REQ_OFFSET_INFO ReqInfo = {0}, NextSpanReqInfo = {0};
1916         GMM_GFX_SIZE_T      SpanPhysicalOffset, SpanVirtualOffset;
1917 
1918         if(pMapping->Type == GMM_MAPPING_YUVPLANAR_AUX)
1919         {
1920             // Unpack GMM_MAPPING_YUVPLANAR and Aux from caller function.
1921             // Applicalble only for Aux mapping for Y/UV Plane
1922             // GMM_MAPPING_YUVPLANAR_AUX is unpacked as (GMM_MAPPING_YUVPLANAR , Aux)
1923             Aux = true;
1924         }
1925 
1926 	if(Aux)
1927         {
1928             memset(pMapping, 0, sizeof(*pMapping));
1929             pMapping->Type                  = GMM_MAPPING_YUVPLANAR;
1930             WasFinalSpan                    = 1;
1931             SpanPhysicalOffset              = GetSizeMainSurfacePhysical();
1932             SpanVirtualOffset               = GetSizeMainSurface();
1933             NextSpanReqInfo.Lock.Offset64   = SpanPhysicalOffset + GetSizeAuxSurface(GMM_AUX_SURF);
1934             NextSpanReqInfo.Render.Offset64 = GetSizeSurface();
1935         }
1936         else
1937         {
1938             if(pMapping->Scratch.Plane == GMM_NO_PLANE)
1939             {
1940                 uint32_t ArrayIndex = pMapping->Scratch.Slice;
1941                 memset(pMapping, 0, sizeof(*pMapping));
1942                 pMapping->Type = GMM_MAPPING_YUVPLANAR;
1943 		pMapping->Scratch.Plane      = GMM_PLANE_Y;
1944                 pMapping->Scratch.Slice = ArrayIndex;
1945 
1946                 SpanPhysicalOffset = SpanVirtualOffset = 0;
1947                 if(GmmLib::Utility::GmmGetNumPlanes(Surf.Format) == GMM_PLANE_V)
1948                 {
1949                     pMapping->Scratch.LastPlane = GMM_PLANE_V;
1950                 }
1951                 else
1952                 {
1953                     pMapping->Scratch.LastPlane = GMM_PLANE_U;
1954                 }
1955 
1956                 Plane = pMapping->Scratch.Plane;
1957             }
1958             else
1959             {
1960                 // If we've crossed into a new plane then need to reset
1961                 // the current mapping info and adjust the mapping
1962                 // params accordingly
1963 
1964                 Plane                   = pMapping->Scratch.Plane + 1;
1965                 GMM_YUV_PLANE LastPlane = pMapping->Scratch.LastPlane;
1966                 SpanPhysicalOffset      = pMapping->__NextSpan.PhysicalOffset;
1967                 SpanVirtualOffset       = pMapping->__NextSpan.VirtualOffset;
1968                 uint32_t ArrayIndex     = pMapping->Scratch.Slice;
1969                 memset(pMapping, 0, sizeof(*pMapping));
1970 
1971                 pMapping->Type               = GMM_MAPPING_YUVPLANAR;
1972                 pMapping->Scratch.Plane      = GMM_YUV_PLANE(Plane);
1973                 pMapping->Scratch.LastPlane  = LastPlane;
1974                 pMapping->Scratch.Slice     = ArrayIndex;
1975             }
1976             {
1977                 if(pMapping->Scratch.Plane == GMM_PLANE_Y)
1978                 {
1979                     ReqInfo.ReqRender = ReqInfo.ReqLock = 1;
1980                     ReqInfo.Plane                       = GMM_YUV_PLANE(Plane);
1981                     ReqInfo.ArrayIndex                  = pMapping->Scratch.Slice;
1982                     this->GetOffset(ReqInfo);
1983                     SpanPhysicalOffset = ReqInfo.Lock.Offset64;
1984                     SpanVirtualOffset  = ReqInfo.Render.Offset64;
1985                 }
1986                 if(GMM_YUV_PLANE(Plane) < pMapping->Scratch.LastPlane)
1987                 {
1988                     NextSpanReqInfo.ReqRender = NextSpanReqInfo.ReqLock = 1;
1989                     NextSpanReqInfo.Plane                               = GMM_YUV_PLANE(Plane + 1);
1990                     NextSpanReqInfo.ArrayIndex                          = pMapping->Scratch.Slice;
1991                     this->GetOffset(NextSpanReqInfo);
1992                 }
1993                 else // last plane of that array
1994                 {
1995                     NextSpanReqInfo.Lock.Offset64   = (GetSizeMainSurfacePhysical() / GFX_MAX(Surf.ArraySize, 1)) * (pMapping->Scratch.Slice + 1);
1996                     NextSpanReqInfo.Render.Offset64 = (GetSizeMainSurface() / GFX_MAX(Surf.ArraySize, 1)) * (pMapping->Scratch.Slice + 1);
1997                     WasFinalSpan                    = 1;
1998                 }
1999             }
2000         }
2001         // Plane offsets
2002         pMapping->Span.PhysicalOffset       = SpanPhysicalOffset;
2003         pMapping->Span.VirtualOffset        = SpanVirtualOffset;
2004         pMapping->__NextSpan.PhysicalOffset = NextSpanReqInfo.Lock.Offset64;
2005         pMapping->__NextSpan.VirtualOffset  = NextSpanReqInfo.Render.Offset64;
2006         pMapping->Span.Size                 = pMapping->__NextSpan.PhysicalOffset - pMapping->Span.PhysicalOffset;
2007 
2008     }
2009     else if(pMapping->Type == GMM_MAPPING_GEN9_YS_TO_STDSWIZZLE)
2010     {
2011         __GMM_ASSERT(Surf.Flags.Info.StdSwizzle);
2012 
2013         const uint32_t TileSize = GMM_KBYTE(64);
2014 
2015         __GMM_ASSERT(Surf.Flags.Info.TiledYs);
2016         __GMM_ASSERT(
2017         (Surf.Type == RESOURCE_2D) ||
2018         (Surf.Type == RESOURCE_3D) ||
2019         (Surf.Type == RESOURCE_CUBE));
2020         __GMM_ASSERT(Surf.Flags.Gpu.Depth == 0); // TODO(Minor): Proper StdSwizzle exemptions?
2021         __GMM_ASSERT(Surf.Flags.Gpu.SeparateStencil == 0);
2022 
2023         __GMM_ASSERT(AuxSurf.Size == 0);       // TODO(Medium): Support not yet implemented, but DX12 UMD not using yet.
2024         __GMM_ASSERT(Surf.Flags.Gpu.MMC == 0); // TODO(Medium): Support not yet implemented, but not yet needed for DX12.
2025 
2026         // For planar surfaces we need to reorder the planes into what HW expects.
2027         // OS will provide planes in [Y0][Y1][U0][U1][V0][V1] order while
2028         // HW requires them to be in [Y0][U0][V0][Y1][U1][V1] order
2029         if(Surf.Flags.Info.RedecribedPlanes)
2030         {
2031             if(pMapping->Scratch.Plane == GMM_NO_PLANE)
2032             {
2033                 pMapping->Scratch.Plane = GMM_PLANE_Y;
2034                 if(GmmLib::Utility::GmmGetNumPlanes(Surf.Format) == GMM_PLANE_V)
2035                 {
2036                     pMapping->Scratch.LastPlane = GMM_PLANE_V;
2037                 }
2038                 else
2039                 {
2040                     pMapping->Scratch.LastPlane = GMM_PLANE_U;
2041                 }
2042             }
2043             else if(pMapping->Scratch.Row == pMapping->Scratch.Rows)
2044             {
2045                 // If we've crossed into a new plane then need to reset
2046                 // the current mapping info and adjust the mapping
2047                 // params accordingly
2048                 GMM_REQ_OFFSET_INFO ReqInfo   = {0};
2049                 uint32_t            Plane     = pMapping->Scratch.Plane + 1;
2050                 GMM_YUV_PLANE       LastPlane = pMapping->Scratch.LastPlane;
2051 
2052                 memset(pMapping, 0, sizeof(*pMapping));
2053 
2054                 pMapping->Type              = GMM_MAPPING_GEN9_YS_TO_STDSWIZZLE;
2055                 pMapping->Scratch.Plane     = GMM_YUV_PLANE(Plane);
2056                 pMapping->Scratch.LastPlane = LastPlane;
2057 
2058                 ReqInfo.ReqRender = ReqInfo.ReqStdLayout = 1;
2059                 ReqInfo.Plane                            = GMM_YUV_PLANE(Plane);
2060 
2061                 this->GetOffset(ReqInfo);
2062 
2063                 pMapping->__NextSpan.PhysicalOffset = ReqInfo.StdLayout.Offset;
2064                 pMapping->__NextSpan.VirtualOffset  = ReqInfo.Render.Offset64;
2065             }
2066 
2067 	    pTextureCalc->GetRedescribedPlaneParams(pTexInfo, GMM_PLANE_Y, &RedescribedPlaneInfo);
2068             pTexInfo = &RedescribedPlaneInfo;
2069 
2070         }
2071 
2072         // Initialization of Mapping Params...
2073         if(pMapping->Scratch.Element.Width == 0) // i.e. initially zero'ed struct.
2074         {
2075             uint32_t BytesPerElement = pTexInfo->BitsPerPixel / CHAR_BIT;
2076 
2077             pMapping->Scratch.EffectiveLodMax = GFX_MIN(pTexInfo->MaxLod, pTexInfo->Alignment.MipTailStartLod);
2078 
2079             pTextureCalc->GetCompressionBlockDimensions(
2080             pTexInfo->Format,
2081             &pMapping->Scratch.Element.Width,
2082             &pMapping->Scratch.Element.Height,
2083             &pMapping->Scratch.Element.Depth);
2084 
2085             { // Tile Dimensions...
2086                 GMM_TILE_MODE TileMode = pTexInfo->TileMode;
2087                 __GMM_ASSERT(TileMode < GMM_TILE_MODES);
2088 
2089                 // Get Tile Logical Tile Dimensions (i.e. uncompressed pixels)...
2090                 pMapping->Scratch.Tile.Width =
2091                 (pPlatform->TileInfo[TileMode].LogicalTileWidth / BytesPerElement) *
2092                 pMapping->Scratch.Element.Width;
2093 
2094                 pMapping->Scratch.Tile.Height =
2095                 pPlatform->TileInfo[TileMode].LogicalTileHeight *
2096                 pMapping->Scratch.Element.Height;
2097 
2098                 pMapping->Scratch.Tile.Depth =
2099                 pPlatform->TileInfo[TileMode].LogicalTileDepth *
2100                 pMapping->Scratch.Element.Depth;
2101 
2102                 pMapping->Scratch.RowPitchVirtual =
2103                 GFX_ULONG_CAST(pTexInfo->Pitch) *
2104                 pPlatform->TileInfo[TileMode].LogicalTileHeight *
2105                 pPlatform->TileInfo[TileMode].LogicalTileDepth;
2106             }
2107 
2108             { // Slice...
2109                 uint32_t Lod;
2110                 uint32_t LodsPerSlice =
2111                 (pTexInfo->Type != RESOURCE_3D) ?
2112                 pMapping->Scratch.EffectiveLodMax + 1 :
2113                 1; // 3D Std Swizzle traverses slices before MIP's.
2114 
2115                 if(pMapping->Scratch.Plane)
2116                 {
2117                     // If planar then we need the parent descriptors planar pitch
2118                     pMapping->Scratch.SlicePitch.Virtual =
2119                     GFX_ULONG_CAST(Surf.OffsetInfo.Plane.ArrayQPitch) *
2120                     (pMapping->Scratch.Tile.Depth / pMapping->Scratch.Element.Depth);
2121                 }
2122                 else
2123                 {
2124                     pMapping->Scratch.SlicePitch.Virtual =
2125                     GFX_ULONG_CAST(pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender) *
2126                     (pMapping->Scratch.Tile.Depth / pMapping->Scratch.Element.Depth);
2127                 }
2128 
2129                 // SlicePitch.Physical...
2130                 __GMM_ASSERT(pMapping->Scratch.SlicePitch.Physical == 0);
2131                 for(Lod = 0; Lod < LodsPerSlice; Lod++)
2132                 {
2133                     uint32_t       MipCols, MipRows;
2134                     GMM_GFX_SIZE_T MipWidth;
2135                     uint32_t       MipHeight;
2136 
2137                     MipWidth  = pTextureCalc->GmmTexGetMipWidth(pTexInfo, Lod);
2138                     MipHeight = pTextureCalc->GmmTexGetMipHeight(pTexInfo, Lod);
2139 
2140                     MipCols = GFX_ULONG_CAST(
2141                     GFX_CEIL_DIV(
2142                     MipWidth,
2143                     pMapping->Scratch.Tile.Width));
2144                     MipRows =
2145                     GFX_CEIL_DIV(
2146                     MipHeight,
2147                     pMapping->Scratch.Tile.Height);
2148 
2149                     pMapping->Scratch.SlicePitch.Physical +=
2150                     MipCols * MipRows * TileSize;
2151                 }
2152             }
2153 
2154             { // Mip0...
2155                 if(pTexInfo->Type != RESOURCE_3D)
2156                 {
2157                     pMapping->Scratch.Slices =
2158                     GFX_MAX(pTexInfo->ArraySize, 1) *
2159                     ((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1);
2160                 }
2161                 else
2162                 {
2163                     pMapping->Scratch.Slices =
2164                     GFX_CEIL_DIV(pTexInfo->Depth, pMapping->Scratch.Tile.Depth);
2165                 }
2166 
2167                 if(pTexInfo->Pitch ==
2168                    (GFX_ALIGN(pTexInfo->BaseWidth, pMapping->Scratch.Tile.Width) /
2169                     pMapping->Scratch.Element.Width * BytesPerElement))
2170                 {
2171                     // Treat Each LOD0 MIP as Single, Large Mapping Row...
2172                     pMapping->Scratch.Rows = 1;
2173 
2174                     pMapping->__NextSpan.Size =
2175                     GFX_CEIL_DIV(pTexInfo->BaseWidth, pMapping->Scratch.Tile.Width) *
2176                     GFX_CEIL_DIV(pTexInfo->BaseHeight, pMapping->Scratch.Tile.Height) *
2177                     TileSize;
2178                 }
2179                 else
2180                 {
2181                     pMapping->Scratch.Rows =
2182                     GFX_CEIL_DIV(pTexInfo->BaseHeight, pMapping->Scratch.Tile.Height);
2183 
2184                     pMapping->__NextSpan.Size =
2185                     GFX_CEIL_DIV(pTexInfo->BaseWidth, pMapping->Scratch.Tile.Width) *
2186                     TileSize;
2187                 }
2188             }
2189         }
2190 
2191         // This iteration's span descriptor...
2192         pMapping->Span = pMapping->__NextSpan;
2193 
2194         // Prepare for Next Iteration...
2195         //  for(Lod = 0; Lod <= EffectiveLodMax; Lod += 1)
2196         //  for(Row = 0; Row < Rows; Row += 1)
2197         //  for(Slice = 0; Slice < Slices; Slice += 1)
2198         if((pMapping->Scratch.Slice += 1) < pMapping->Scratch.Slices)
2199         {
2200             pMapping->__NextSpan.PhysicalOffset += pMapping->Scratch.SlicePitch.Physical;
2201             pMapping->__NextSpan.VirtualOffset += pMapping->Scratch.SlicePitch.Virtual;
2202         }
2203         else
2204         {
2205             pMapping->Scratch.Slice = 0;
2206 
2207             if((pMapping->Scratch.Row += 1) < pMapping->Scratch.Rows)
2208             {
2209                 pMapping->__NextSpan.PhysicalOffset =
2210                 pMapping->Scratch.Slice0MipOffset.Physical += pMapping->Span.Size;
2211 
2212                 pMapping->__NextSpan.VirtualOffset =
2213                 pMapping->Scratch.Slice0MipOffset.Virtual += pMapping->Scratch.RowPitchVirtual;
2214             }
2215             else if((pMapping->Scratch.Lod += 1) <= pMapping->Scratch.EffectiveLodMax)
2216             {
2217                 GMM_REQ_OFFSET_INFO GetOffset = {0};
2218                 GMM_GFX_SIZE_T      MipWidth;
2219                 uint32_t            MipHeight, MipCols;
2220 
2221                 MipWidth  = pTextureCalc->GmmTexGetMipWidth(pTexInfo, pMapping->Scratch.Lod);
2222                 MipHeight = pTextureCalc->GmmTexGetMipHeight(pTexInfo, pMapping->Scratch.Lod);
2223 
2224                 MipCols = GFX_ULONG_CAST(
2225                 GFX_CEIL_DIV(
2226                 MipWidth,
2227                 pMapping->Scratch.Tile.Width));
2228 
2229                 pMapping->Scratch.Row = 0;
2230                 pMapping->Scratch.Rows =
2231                 GFX_CEIL_DIV(
2232                 MipHeight,
2233                 pMapping->Scratch.Tile.Height);
2234 
2235                 if(pTexInfo->Type != RESOURCE_3D)
2236                 {
2237                     pMapping->__NextSpan.PhysicalOffset =
2238                     pMapping->Scratch.Slice0MipOffset.Physical += pMapping->Span.Size;
2239                 }
2240                 else
2241                 {
2242                     uint32_t MipDepth;
2243 
2244                     MipDepth = pTextureCalc->GmmTexGetMipDepth(pTexInfo, pMapping->Scratch.Lod);
2245 
2246                     // 3D Std Swizzle traverses slices before MIP's...
2247                     pMapping->Scratch.Slice0MipOffset.Physical =
2248                     pMapping->__NextSpan.PhysicalOffset += pMapping->Span.Size;
2249 
2250                     pMapping->Scratch.Slices =
2251                     GFX_CEIL_DIV(
2252                     MipDepth,
2253                     pMapping->Scratch.Tile.Depth);
2254 
2255                     pMapping->Scratch.SlicePitch.Physical =
2256                     MipCols * pMapping->Scratch.Rows * TileSize;
2257                 }
2258 
2259                 GetOffset.ReqRender = 1;
2260                 GetOffset.MipLevel  = pMapping->Scratch.Lod;
2261                 this->GetOffset(GetOffset);
2262 
2263                 pMapping->__NextSpan.VirtualOffset =
2264                 pMapping->Scratch.Slice0MipOffset.Virtual =
2265                 GFX_ALIGN_FLOOR(GetOffset.Render.Offset64, TileSize); // Truncate for packed MIP Tail.
2266 
2267                 pMapping->__NextSpan.Size = MipCols * TileSize;
2268             }
2269             else
2270             {
2271                 // If the resource was a planar surface then need to iterate over the remaining planes
2272                 WasFinalSpan = pMapping->Scratch.Plane == pMapping->Scratch.LastPlane;
2273             }
2274         }
2275     }
2276     else
2277     {
2278         __GMM_ASSERT(0);
2279     }
2280 
2281     return !WasFinalSpan;
2282 }
2283 
2284 //=============================================================================
2285 //
2286 // Function: GetTiledResourceMipPacking
2287 //
2288 // Desc: Get number of packed mips and total #tiles for packed mips
2289 //
2290 // Parameters:
2291 //      See function arguments.
2292 //
2293 // Returns:
2294 //      void
2295 //-----------------------------------------------------------------------------
GetTiledResourceMipPacking(uint32_t * pNumPackedMips,uint32_t * pNumTilesForPackedMips)2296 void GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetTiledResourceMipPacking(uint32_t *pNumPackedMips,
2297                                                                            uint32_t *pNumTilesForPackedMips)
2298 {
2299     if(GetMaxLod() == 0)
2300     {
2301         *pNumPackedMips         = 0;
2302         *pNumTilesForPackedMips = 0;
2303         return;
2304     }
2305 
2306     if(GetResFlags().Info.TiledYf ||
2307        GMM_IS_64KB_TILE(GetResFlags()))
2308     {
2309         if(Surf.Alignment.MipTailStartLod == GMM_TILED_RESOURCE_NO_MIP_TAIL)
2310         {
2311             *pNumPackedMips         = 0;
2312             *pNumTilesForPackedMips = 0;
2313         }
2314         else
2315         {
2316             *pNumPackedMips = GetMaxLod() -
2317                               Surf.Alignment.MipTailStartLod + 1;
2318             *pNumTilesForPackedMips = 1;
2319         }
2320     }
2321     else
2322     {
2323         // Error, unsupported format.
2324         __GMM_ASSERT(false);
2325     }
2326 }
2327 
2328 //=============================================================================
2329 //
2330 // Function: GetPackedMipTailStartLod
2331 //
2332 // Desc: Get Lod of first packed Mip.
2333 //
2334 // Parameters:
2335 //      See function arguments.
2336 //
2337 // Returns:
2338 //      Lod of first packed Mip
2339 //-----------------------------------------------------------------------------
GetPackedMipTailStartLod()2340 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetPackedMipTailStartLod()
2341 
2342 {
2343     uint32_t NumPackedMips = 0, NumTilesForPackedMips = 0;
2344 
2345     const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(&Surf, GetGmmLibContext());
2346 
2347     GetTiledResourceMipPacking(&NumPackedMips,
2348                                &NumTilesForPackedMips);
2349 
2350     return (GetMaxLod() == 0) ?
2351            pPlatform->MaxLod :
2352            GetMaxLod() - NumPackedMips + 1; //GetMaxLod srarts at index 0, while NumPackedMips is just
2353                                             //the number of mips. So + 1 to bring them to same units.
2354 }
2355 
2356 /////////////////////////////////////////////////////////////////////////////////////
2357 /// Verifies if all mips are RCC-aligned
2358 /// @return    true/false
2359 /////////////////////////////////////////////////////////////////////////////////////
IsMipRCCAligned(uint8_t & MisAlignedLod)2360 bool GMM_STDCALL GmmLib::GmmResourceInfoCommon::IsMipRCCAligned(uint8_t &MisAlignedLod)
2361 {
2362     const uint8_t RCCCachelineWidth  = 32;
2363     const uint8_t RCCCachelineHeight = 4;
2364 
2365     for(uint8_t lod = 0; lod <= GetMaxLod(); lod++)
2366     {
2367         if(!(GFX_IS_ALIGNED(GetMipWidth(lod), RCCCachelineWidth) &&
2368              GFX_IS_ALIGNED(GetMipHeight(lod), RCCCachelineHeight)))
2369         {
2370             MisAlignedLod = lod;
2371             return false;
2372         }
2373     }
2374     return true;
2375 }
2376 
2377 /////////////////////////////////////////////////////////////////////////////////////
2378 /// Return the logical width of mip level
2379 /// @param[in] MipLevel: Mip level for which the info is needed
2380 /// @return    Mip width
2381 /////////////////////////////////////////////////////////////////////////////////////
GetMipWidth(uint32_t MipLevel)2382 GMM_GFX_SIZE_T GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetMipWidth(uint32_t MipLevel)
2383 {
2384     GMM_TEXTURE_CALC *pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
2385     return pTextureCalc->GmmTexGetMipWidth(&Surf, MipLevel);
2386 }
2387 
2388 /////////////////////////////////////////////////////////////////////////////////////
2389 /// Return the logical height of mip level
2390 /// @param[in] MipLevel: Mip level for which the info is needed
2391 /// @return    Mip width
2392 /////////////////////////////////////////////////////////////////////////////////////
GetMipHeight(uint32_t MipLevel)2393 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetMipHeight(uint32_t MipLevel)
2394 {
2395     GMM_TEXTURE_CALC *pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
2396     return pTextureCalc->GmmTexGetMipHeight(&Surf, MipLevel);
2397 }
2398 
2399 /////////////////////////////////////////////////////////////////////////////////////
2400 /// Return the logical depth of mip level
2401 /// @param[in] MipLevel Mip level for which the info is needed
2402 /// @return    Mip width
2403 /////////////////////////////////////////////////////////////////////////////////////
GetMipDepth(uint32_t MipLevel)2404 uint32_t GMM_STDCALL GmmLib::GmmResourceInfoCommon::GetMipDepth(uint32_t MipLevel)
2405 {
2406     GMM_TEXTURE_CALC *pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf, GetGmmLibContext());
2407     return pTextureCalc->GmmTexGetMipDepth(&Surf, MipLevel);
2408 }
2409