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