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