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