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 /////////////////////////////////////////////////////////////////////////////////////
27 /// Calculates the mip offset of given LOD in 1D mip layout
28 ///
29 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
30 ///
31 /// @return offset value in bytes
32 /////////////////////////////////////////////////////////////////////////////////////
Get1DTexOffsetAddressPerMip(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel)33 GMM_GFX_SIZE_T GmmLib::GmmGen9TextureCalc::Get1DTexOffsetAddressPerMip(GMM_TEXTURE_INFO *pTexInfo,
34 uint32_t MipLevel)
35 {
36 uint32_t AlignedMipWidth, MipWidth, __MipLevel;
37 uint32_t i, HAlign;
38 GMM_GFX_SIZE_T MipOffset = 0;
39 uint8_t Compressed;
40 uint32_t CompressHeight, CompressWidth, CompressDepth;
41
42 GMM_DPF_ENTER;
43
44 HAlign = pTexInfo->Alignment.HAlign;
45 MipWidth = GFX_ULONG_CAST(pTexInfo->BaseWidth);
46
47 __MipLevel =
48 (pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) ?
49 GFX_MIN(MipLevel, pTexInfo->Alignment.MipTailStartLod) :
50 MipLevel;
51
52 Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
53 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
54
55 for(i = 1; i <= __MipLevel; i++)
56 {
57 AlignedMipWidth = __GMM_EXPAND_WIDTH(this, MipWidth, HAlign, pTexInfo);
58
59 if(Compressed)
60 {
61 AlignedMipWidth /= CompressWidth;
62 }
63
64 MipOffset += AlignedMipWidth;
65
66 MipWidth = GFX_ULONG_CAST(GmmTexGetMipWidth(pTexInfo, i));
67 }
68
69 MipOffset *= (pTexInfo->BitsPerPixel >> 3);
70
71 if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
72 (MipLevel >= pTexInfo->Alignment.MipTailStartLod))
73 {
74 MipOffset += GetMipTailByteOffset(pTexInfo, MipLevel);
75 }
76
77 GMM_DPF_EXIT;
78
79 return (MipOffset);
80 }
81
82
83 /////////////////////////////////////////////////////////////////////////////////////
84 /// Calculates the address offset for each mip map of 1D texture and store them into
85 /// the GMM_TEXTURE_INFO for surf state programming.
86 ///
87 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
88 ///
89 /////////////////////////////////////////////////////////////////////////////////////
Fill1DTexOffsetAddress(GMM_TEXTURE_INFO * pTexInfo)90 void GmmLib::GmmGen9TextureCalc::Fill1DTexOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
91 {
92 uint32_t i;
93
94 GMM_DPF_ENTER;
95
96 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
97 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock =
98 pTexInfo->Alignment.QPitch * pTexInfo->BitsPerPixel >> 3;
99
100 for(i = 0; i <= pTexInfo->MaxLod; i++)
101 {
102 pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[i] = Get1DTexOffsetAddressPerMip(pTexInfo, i);
103 }
104
105 GMM_DPF_EXIT;
106 }
107
108
109 /////////////////////////////////////////////////////////////////////////////////////
110 /// Allocates the 1D mip layout for surface state programming.
111 ///
112 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
113 /// @param[in] pRestrictions: ptr to surface alignment and size restrictions
114 ///
115 /// @return ::GMM_STATUS
116 /////////////////////////////////////////////////////////////////////////////////////
FillTex1D(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)117 GMM_STATUS GMM_STDCALL GmmLib::GmmGen9TextureCalc::FillTex1D(GMM_TEXTURE_INFO * pTexInfo,
118 __GMM_BUFFER_TYPE *pRestrictions)
119 {
120 uint32_t ArraySize, BitsPerPixel, HAlign, i, Width, MipWidth;
121 int64_t Size;
122 GMM_STATUS Status = GMM_SUCCESS;
123 uint8_t Compressed;
124 uint32_t CompressHeight, CompressWidth, CompressDepth;
125
126 GMM_DPF_ENTER;
127
128 __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
129 __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
130 __GMM_ASSERT(pTexInfo->Flags.Info.Linear ||
131 pTexInfo->Flags.Info.TiledYf ||
132 GMM_IS_64KB_TILE(pTexInfo->Flags));
133
134 pTexInfo->Flags.Info.Linear = 1;
135 pTexInfo->Flags.Info.TiledW = 0;
136 pTexInfo->Flags.Info.TiledX = 0;
137 GMM_SET_4KB_TILE(pTexInfo->Flags, 0, pGmmLibContext);
138
139 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
140
141 ArraySize = GFX_MAX(pTexInfo->ArraySize, 1);
142 BitsPerPixel = pTexInfo->BitsPerPixel;
143 HAlign = pTexInfo->Alignment.HAlign;
144
145 Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
146 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
147
148 if(pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags))
149 {
150 FindMipTailStartLod(pTexInfo);
151 }
152
153 /////////////////////////////
154 // Calculate Surface QPitch
155 /////////////////////////////
156
157 Width = __GMM_EXPAND_WIDTH(this, GFX_ULONG_CAST(pTexInfo->BaseWidth), HAlign, pTexInfo);
158 MipWidth = Width;
159
160 if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
161 ((pTexInfo->Alignment.MipTailStartLod == 0) || (pTexInfo->MaxLod == 0)))
162 {
163 // Do nothing. Width is already aligned.
164 }
165 else
166 {
167 for(i = 1; i <= pTexInfo->MaxLod; i++)
168 {
169 uint32_t AlignedMipWidth;
170
171 if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
172 (i == pTexInfo->Alignment.MipTailStartLod))
173 {
174 Width += pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth;
175 break;
176 }
177 else
178 {
179 MipWidth = GFX_ULONG_CAST(GmmTexGetMipWidth(pTexInfo, i));
180
181 AlignedMipWidth = __GMM_EXPAND_WIDTH(this, MipWidth, HAlign, pTexInfo);
182
183 if(Compressed)
184 {
185 AlignedMipWidth /= CompressWidth;
186 }
187
188 Width += AlignedMipWidth;
189 }
190 }
191 }
192
193 pTexInfo->Alignment.QPitch = GFX_ALIGN((ArraySize > 1) ? Width : 0, HAlign); // in pixels
194
195 pTexInfo->Pitch = 0;
196
197 ///////////////////////////
198 // Calculate Surface Size
199 ///////////////////////////
200
201 Width *= BitsPerPixel >> 3;
202
203 Size = GFX_ALIGN((uint64_t)Width * ArraySize, PAGE_SIZE);
204
205 if(Size <= pPlatform->SurfaceMaxSize)
206 {
207 pTexInfo->Size = Size;
208
209 Fill1DTexOffsetAddress(pTexInfo);
210 }
211 else
212 {
213 GMM_ASSERTDPF(0, "Surface too large!");
214 Status = GMM_ERROR;
215 }
216
217 //////////////////////
218 // Surface Alignment
219 //////////////////////
220
221 if(!pTexInfo->Alignment.BaseAlignment || __GMM_IS_ALIGN(pRestrictions->Alignment, pTexInfo->Alignment.BaseAlignment))
222 {
223 pTexInfo->Alignment.BaseAlignment = pRestrictions->Alignment;
224 }
225 else if(__GMM_IS_ALIGN(pTexInfo->Alignment.BaseAlignment, pRestrictions->Alignment))
226 {
227 // Do nothing: pTexInfo->Alignment.BaseAlignment is properly aligned
228 }
229 else
230 {
231 pTexInfo->Alignment.BaseAlignment = pTexInfo->Alignment.BaseAlignment * pRestrictions->Alignment;
232 GMM_ASSERTDPF(0,
233 "Client requested alignment that is not properly aligned to HW requirements."
234 "Alignment is going to be much higher to match both client and HW requirements.\r\n");
235 }
236
237 GMM_DPF_EXIT;
238
239 return (Status);
240 }
241
242
243 /////////////////////////////////////////////////////////////////////////////////////
244 /// Calculates height of the 2D mip layout on Gen9
245 ///
246 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
247 ///
248 /// @return height of 2D mip layout
249 /////////////////////////////////////////////////////////////////////////////////////
Get2DMipMapHeight(GMM_TEXTURE_INFO * pTexInfo)250 uint32_t GmmLib::GmmGen9TextureCalc::Get2DMipMapHeight(GMM_TEXTURE_INFO *pTexInfo)
251 {
252 uint32_t BlockHeight, MipHeight;
253 uint32_t HeightLinesLevel0, HeightLinesLevel1, HeightLinesLevel2;
254 uint32_t i, MipLevel, VAlign, CompressHeight, CompressWidth, CompressDepth;
255 uint8_t Compressed;
256 GMM_DPF_ENTER;
257
258 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
259
260 Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
261 MipHeight = pTexInfo->BaseHeight;
262 MipLevel = pTexInfo->MaxLod;
263 VAlign = pTexInfo->Alignment.VAlign;
264 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
265
266 HeightLinesLevel0 = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
267
268 if(Compressed)
269 {
270 HeightLinesLevel0 /= CompressHeight;
271 }
272 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
273 {
274 HeightLinesLevel0 /= 2;
275 }
276 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
277 {
278 HeightLinesLevel0 /= 16;
279 }
280
281 // Mip0 height...
282 BlockHeight = HeightLinesLevel0;
283
284 if((pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs) &&
285 ((pTexInfo->Alignment.MipTailStartLod == 0) || (pTexInfo->MaxLod == 0)))
286 {
287 // Do nothing. Height is already aligned.
288 }
289 else
290 {
291 // Height of Mip1 and Mip2..n needed later...
292 HeightLinesLevel1 = HeightLinesLevel2 = 0;
293 for(i = 1; i <= MipLevel; i++)
294 {
295 uint32_t AlignedHeightLines;
296
297 if((pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs) &&
298 (i == pTexInfo->Alignment.MipTailStartLod))
299 {
300 AlignedHeightLines = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
301
302 if(i == 1)
303 {
304 HeightLinesLevel1 = AlignedHeightLines;
305 }
306 else
307 {
308 HeightLinesLevel2 += AlignedHeightLines;
309 }
310
311 break;
312 }
313 else
314 {
315 MipHeight = GmmTexGetMipHeight(pTexInfo, i);
316
317 AlignedHeightLines = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
318
319 if(Compressed)
320 {
321 AlignedHeightLines /= CompressHeight;
322 }
323 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
324 {
325 AlignedHeightLines /= 2;
326 }
327 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
328 {
329 AlignedHeightLines /= 16;
330 }
331
332 if(i == 1)
333 {
334 HeightLinesLevel1 = AlignedHeightLines;
335 }
336 else
337 {
338 HeightLinesLevel2 += AlignedHeightLines;
339 }
340 }
341 }
342
343 // If Mip1 height covers all others, then that is all we need...
344 if(!(pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs))
345 {
346 if(HeightLinesLevel1 >= HeightLinesLevel2)
347 {
348 BlockHeight += GFX_ALIGN(HeightLinesLevel1, VAlign);
349 }
350 else
351 {
352 BlockHeight += GFX_ALIGN(HeightLinesLevel2, VAlign);
353 }
354 }
355 else
356 {
357 //TR mode- requires TileMode height alignment
358 BlockHeight += (HeightLinesLevel1 >= HeightLinesLevel2) ? HeightLinesLevel1 : HeightLinesLevel2;
359 BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
360 }
361 }
362
363 GMM_DPF_EXIT;
364
365 return (BlockHeight);
366 }
367
368
369 /////////////////////////////////////////////////////////////////////////////////////
370 /// Calculates total height of an arrayed 2D/3D mip layout
371 ///
372 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
373 ///
374 /// @return height of arrayed 2D/3D mip layout
375 /////////////////////////////////////////////////////////////////////////////////////
Get2DMipMapTotalHeight(GMM_TEXTURE_INFO * pTexInfo)376 uint32_t GmmLib::GmmGen9TextureCalc::Get2DMipMapTotalHeight(GMM_TEXTURE_INFO *pTexInfo)
377 {
378 uint32_t BlockHeight, MipHeight;
379 uint32_t HeightLinesLevel0, HeightLinesLevel1, HeightLinesLevel2;
380 uint32_t i, MipLevel, VAlign;
381 uint32_t AlignedHeightLines;
382
383 GMM_DPF_ENTER;
384
385 MipHeight = pTexInfo->BaseHeight;
386 MipLevel = pTexInfo->MaxLod;
387 VAlign = pTexInfo->Alignment.VAlign;
388
389 MipLevel =
390 (pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) ?
391 GFX_MIN(MipLevel, pTexInfo->Alignment.MipTailStartLod) :
392 MipLevel;
393
394
395 HeightLinesLevel0 = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
396
397 // Mip0 height...
398 BlockHeight = HeightLinesLevel0;
399
400 // Height of Mip1 and Mip2..n needed later...
401 HeightLinesLevel1 = HeightLinesLevel2 = 0;
402 for(i = 1; i <= MipLevel; i++)
403 {
404 MipHeight = GmmTexGetMipHeight(pTexInfo, i);
405
406 AlignedHeightLines = __GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo);
407
408 if(i == 1)
409 {
410 HeightLinesLevel1 = AlignedHeightLines;
411 }
412 else
413 {
414 HeightLinesLevel2 += AlignedHeightLines;
415 }
416 }
417
418 // If Mip1 height covers all others, then that is all we need...
419 if(HeightLinesLevel1 >= HeightLinesLevel2)
420 {
421 BlockHeight += HeightLinesLevel1;
422 }
423 else
424 {
425 BlockHeight += HeightLinesLevel2;
426 }
427
428 GMM_DPF_EXIT;
429
430 return (BlockHeight);
431 }
432
433
434 /////////////////////////////////////////////////////////////////////////////////////
435 /// Calculates the mip offset of given LOD in 2D/3D mip layout
436 ///
437 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
438 ///
439 /// @return ::GMM_GFX_SIZE_T offset value in bytes
440 /////////////////////////////////////////////////////////////////////////////////////
Get2DTexOffsetAddressPerMip(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel)441 GMM_GFX_SIZE_T GmmLib::GmmGen9TextureCalc::Get2DTexOffsetAddressPerMip(GMM_TEXTURE_INFO *pTexInfo,
442 uint32_t MipLevel)
443 {
444 uint32_t AlignedMipHeight, i, OffsetHeight;
445 uint8_t Compressed;
446 uint32_t HAlign, VAlign, __MipLevel;
447 uint32_t CompressHeight, CompressWidth, CompressDepth;
448 uint32_t MipHeight;
449 GMM_GFX_SIZE_T MipOffset;
450
451 GMM_DPF_ENTER;
452
453 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
454
455 HAlign = pTexInfo->Alignment.HAlign;
456 VAlign = pTexInfo->Alignment.VAlign;
457 Compressed = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
458
459 MipHeight = pTexInfo->BaseHeight;
460 OffsetHeight = 0;
461
462 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
463
464 __MipLevel =
465 (pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) ?
466 GFX_MIN(MipLevel, pTexInfo->Alignment.MipTailStartLod) :
467 MipLevel;
468
469 if(__MipLevel < 2) // LOD0 and LOD1 are on the left edge...
470 {
471 MipOffset = 0;
472 }
473 else // LOD2 and beyond are to the right of LOD1...
474 {
475 uint32_t MipWidth = GFX_ULONG_CAST(GmmTexGetMipWidth(pTexInfo, 1));
476 uint32_t BitsPerPixel = pTexInfo->BitsPerPixel;
477
478 MipWidth = __GMM_EXPAND_WIDTH(this, MipWidth, HAlign, pTexInfo);
479
480 if(Compressed)
481 {
482 MipWidth /= CompressWidth;
483 }
484 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
485 {
486 //Expt: Stencil Row interleaving, where Rowheight = VALign=8
487 //XOffset on interleaved row not different than w/o interleave.
488 //MipWidth *= 2;
489 }
490 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
491 {
492 BitsPerPixel = 8; // Aux Surfaces are 8bpp
493
494 switch(pTexInfo->BitsPerPixel)
495 {
496 case 32:
497 MipWidth /= 8;
498 break;
499 case 64:
500 MipWidth /= 4;
501 break;
502 case 128:
503 MipWidth /= 2;
504 break;
505 default:
506 __GMM_ASSERT(0);
507 }
508 }
509
510 MipOffset = (GMM_GFX_SIZE_T)MipWidth * BitsPerPixel >> 3;
511 }
512
513 for(i = 1; i <= __MipLevel; i++)
514 {
515 AlignedMipHeight = GFX_ULONG_CAST(__GMM_EXPAND_HEIGHT(this, MipHeight, VAlign, pTexInfo));
516
517 if(Compressed)
518 {
519 AlignedMipHeight /= CompressHeight;
520 }
521 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
522 {
523 AlignedMipHeight /= 2;
524 }
525 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
526 {
527 AlignedMipHeight /= 16;
528 }
529
530 OffsetHeight += ((i != 2) ? AlignedMipHeight : 0);
531
532 MipHeight = GmmTexGetMipHeight(pTexInfo, i);
533 }
534 OffsetHeight *= GFX_MAX(pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth, 1);
535
536 MipOffset += OffsetHeight * GFX_ULONG_CAST(pTexInfo->Pitch);
537
538 if((pTexInfo->Flags.Info.TiledYf || GMM_IS_64KB_TILE(pTexInfo->Flags)) &&
539 (MipLevel >= pTexInfo->Alignment.MipTailStartLod))
540 {
541 MipOffset += GetMipTailByteOffset(pTexInfo, MipLevel);
542 }
543
544 GMM_DPF_EXIT;
545 return (MipOffset);
546 }
547
548
549 /////////////////////////////////////////////////////////////////////////////////////
550 /// Calculates the address offset for each mip map of 2D texture and store them into
551 /// the GMM_TEXTURE_INFO for surf state programming.
552 ///
553 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
554 ///
555 /////////////////////////////////////////////////////////////////////////////////////
Fill2DTexOffsetAddress(GMM_TEXTURE_INFO * pTexInfo)556 void GmmLib::GmmGen9TextureCalc::Fill2DTexOffsetAddress(GMM_TEXTURE_INFO *pTexInfo)
557 {
558 uint32_t i;
559 GMM_DPF_ENTER;
560
561 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
562
563 // QPitch: Array Element-to-Element, or Cube Face-to-Face Pitch...
564 if((pTexInfo->ArraySize <= 1) &&
565 (pTexInfo->Type != RESOURCE_3D) &&
566 (pTexInfo->Type != RESOURCE_CUBE) &&
567 !(pTexInfo->Flags.Gpu.ColorSeparation ||
568 pTexInfo->Flags.Gpu.ColorSeparationRGBX))
569 {
570 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
571 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = 0;
572 }
573 else
574 {
575 uint32_t ArrayQPitch, Alignment;
576
577 Alignment = pTexInfo->Alignment.VAlign;
578 if((pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear) ||
579 (pTexInfo->Flags.Gpu.S3dDx && pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d) ||
580 (pTexInfo->Flags.Wa.MediaPipeUsage))
581 {
582 Alignment = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
583 //Gmm uses TileY for Stencil allocations, having half TileW height (TileY width compensates)
584 if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
585 {
586 Alignment *= 2;
587 }
588 }
589
590 // Calculate the overall Block height...Mip0Height + Max(Mip1Height, Sum of Mip2Height..MipnHeight)
591 ArrayQPitch = Get2DMipMapTotalHeight(pTexInfo);
592 ArrayQPitch = GFX_ALIGN_NP2(ArrayQPitch, Alignment);
593
594 // Color Surf with MSAA Enabled Mutiply 4
595 if (GMM_IS_64KB_TILE(pTexInfo->Flags) && (!pGmmLibContext->GetSkuTable().FtrTileY) && (!pGmmLibContext->GetSkuTable().FtrXe2PlusTiling) &&
596 ((pTexInfo->MSAA.NumSamples == 8) || (pTexInfo->MSAA.NumSamples == 16)) &&
597 ((pTexInfo->Flags.Gpu.Depth == 0) && (pTexInfo->Flags.Gpu.SeparateStencil == 0)))
598 {
599 // ArrayQPitch *= 4; /* Aligned height of 4 samples */
600 }
601
602 pTexInfo->Alignment.QPitch = ArrayQPitch;
603
604 if(GmmIsCompressed(pGmmLibContext, pTexInfo->Format))
605 {
606 uint32_t CompressWidth, CompressHeight, CompressDepth;
607
608 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
609
610 ArrayQPitch /= CompressHeight;
611
612 if((pTexInfo->Type == RESOURCE_3D) && !pTexInfo->Flags.Info.Linear)
613 {
614 ArrayQPitch = GFX_ALIGN(ArrayQPitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
615 }
616 }
617 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
618 {
619 ArrayQPitch /= 2;
620 if(pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear)
621 {
622 pTexInfo->Alignment.QPitch = ArrayQPitch;
623 }
624 }
625 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
626 {
627 ArrayQPitch /= 16;
628 }
629
630 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchRender =
631 pTexInfo->OffsetInfo.Texture2DOffsetInfo.ArrayQPitchLock = ArrayQPitch * pTexInfo->Pitch;
632 }
633
634 for(i = 0; i <= pTexInfo->MaxLod; i++)
635 {
636 pTexInfo->OffsetInfo.Texture2DOffsetInfo.Offset[i] = Get2DTexOffsetAddressPerMip(pTexInfo, i);
637 }
638
639 GMM_DPF_EXIT;
640 }
641
642 /////////////////////////////////////////////////////////////////////////////////////
643 /// Returns the aligned block height of the 3D surface on Gen9
644 ///
645 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
646 /// BlockHeight: Unaligned block height
647 /// ExpandedArraySize: adjusted array size for MSAA, cube faces, etc.
648 ///
649 /// @return Aligned BlockHeight
650 /////////////////////////////////////////////////////////////////////////////////////
GetAligned3DBlockHeight(GMM_TEXTURE_INFO * pTexInfo,uint32_t BlockHeight,uint32_t ExpandedArraySize)651 uint32_t GmmLib::GmmGen9TextureCalc::GetAligned3DBlockHeight(GMM_TEXTURE_INFO *pTexInfo,
652 uint32_t BlockHeight,
653 uint32_t ExpandedArraySize)
654 {
655 GMM_DPF_ENTER;
656
657 GMM_UNREFERENCED_PARAMETER(ExpandedArraySize);
658 __GMM_ASSERTPTR(pTexInfo, 0);
659
660 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
661
662 if((pTexInfo->Type == RESOURCE_3D) && !pTexInfo->Flags.Info.Linear)
663 {
664 BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
665 }
666
667 GMM_DPF_EXIT;
668
669 return BlockHeight;
670 }
671
672 /////////////////////////////////////////////////////////////////////////////////////
673 /// Allocates the 2D mip layout for surface state programming.
674 ///
675 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
676 /// @param[in] pRestrictions: ptr to surface alignment and size restrictions
677 ///
678 /// @return ::GMM_STATUS
679 /////////////////////////////////////////////////////////////////////////////////////
FillTex2D(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)680 GMM_STATUS GMM_STDCALL GmmLib::GmmGen9TextureCalc::FillTex2D(GMM_TEXTURE_INFO * pTexInfo,
681 __GMM_BUFFER_TYPE *pRestrictions)
682 {
683 uint32_t Width, Height, BitsPerPixel;
684 uint32_t HAlign, VAlign, DAlign, CompressHeight, CompressWidth, CompressDepth;
685 uint32_t AlignedWidth, BlockHeight, ExpandedArraySize, Pitch;
686 uint8_t Compress = 0;
687 GMM_STATUS Status;
688
689 GMM_DPF_ENTER;
690
691 __GMM_ASSERTPTR(pTexInfo, GMM_ERROR);
692 __GMM_ASSERTPTR(pRestrictions, GMM_ERROR);
693
694 const GMM_PLATFORM_INFO *pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo, pGmmLibContext);
695
696 BitsPerPixel = pTexInfo->BitsPerPixel;
697 if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
698 {
699 // Aux Surfaces are 8bpp.
700 BitsPerPixel = 8;
701 }
702
703 Height = pTexInfo->BaseHeight;
704 Width = GFX_ULONG_CAST(pTexInfo->BaseWidth);
705
706 pTexInfo->MSAA.NumSamples = GFX_MAX(pTexInfo->MSAA.NumSamples, 1);
707
708 if(pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs)
709 {
710 FindMipTailStartLod(pTexInfo);
711 }
712
713 ExpandedArraySize =
714 GFX_MAX(pTexInfo->ArraySize, 1) *
715 ((pTexInfo->Type == RESOURCE_CUBE) ? 6 : 1) * // Cubemaps simply 6-element, 2D arrays.
716 ((pTexInfo->Type == RESOURCE_3D) ? pTexInfo->Depth : 1) * // 3D's simply 2D arrays.
717 ((pTexInfo->Flags.Gpu.Depth || pTexInfo->Flags.Gpu.SeparateStencil ||
718 (pTexInfo->Flags.Info.TiledYs || pTexInfo->Flags.Info.TiledYf)) ? // MSAA Ys samples are NOT stored as array planes.
719 1 :
720 pTexInfo->MSAA.NumSamples); // MSAA (non-Depth/Stencil) RT samples stored as array planes.
721
722 if(pTexInfo->Flags.Info.TiledYs || pTexInfo->Flags.Info.TiledYf)
723 {
724 ExpandedArraySize = GFX_CEIL_DIV(ExpandedArraySize, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileDepth);
725 }
726
727 //
728 // Check for color separation
729 //
730 if(pTexInfo->Flags.Gpu.ColorSeparation || pTexInfo->Flags.Gpu.ColorSeparationRGBX)
731 {
732 bool csRestrictionsMet = (((ExpandedArraySize <= 2) &&
733 (ExpandedArraySize == pTexInfo->ArraySize) &&
734 ((pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM) ||
735 (pTexInfo->Format == GMM_FORMAT_R8G8B8A8_UNORM_SRGB) ||
736 (pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM) ||
737 (pTexInfo->Format == GMM_FORMAT_B8G8R8A8_UNORM_SRGB) ||
738 (pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM) ||
739 (pTexInfo->Format == GMM_FORMAT_B8G8R8X8_UNORM_SRGB)) &&
740 ((pTexInfo->Flags.Gpu.ColorSeparation && (Width % 16) == 0) ||
741 (pTexInfo->Flags.Gpu.ColorSeparationRGBX && (Width % 12) == 0))));
742
743 if(csRestrictionsMet)
744 {
745 ExpandedArraySize = GMM_COLOR_SEPARATION_ARRAY_SIZE;
746 }
747 else
748 {
749 pTexInfo->Flags.Gpu.ColorSeparation = false;
750 pTexInfo->Flags.Gpu.ColorSeparationRGBX = false;
751 }
752 }
753
754 HAlign = pTexInfo->Alignment.HAlign;
755 VAlign = pTexInfo->Alignment.VAlign;
756 DAlign = pTexInfo->Alignment.DAlign;
757 GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth);
758
759 Compress = GmmIsCompressed(pGmmLibContext, pTexInfo->Format);
760
761 /////////////////////////////////
762 // Calculate Block Surface Height
763 /////////////////////////////////
764
765 if(ExpandedArraySize > 1)
766 {
767 uint32_t Alignment = VAlign;
768 if((pTexInfo->Type == RESOURCE_3D && !pTexInfo->Flags.Info.Linear) ||
769 (pTexInfo->Flags.Gpu.S3dDx && pGmmLibContext->GetSkuTable().FtrDisplayEngineS3d) ||
770 (pTexInfo->Flags.Wa.MediaPipeUsage))
771 {
772 Alignment = pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight;
773 //Gmm uses TileY for Stencil allocations, having half TileW height (TileY width compensates)
774 if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
775 {
776 Alignment *= 2;
777 }
778 }
779
780 // Calculate the overall Block height...Mip0Height + Max(Mip1Height, Sum of Mip2Height..MipnHeight)
781 BlockHeight = Get2DMipMapTotalHeight(pTexInfo);
782 BlockHeight = GFX_ALIGN_NP2(BlockHeight, Alignment);
783
784 // GMM internally uses QPitch as the logical distance between slices, but translates
785 // as appropriate to service client queries in GmmResGetQPitch.
786 pTexInfo->Alignment.QPitch = BlockHeight;
787
788 if(Compress)
789 {
790 BlockHeight = GFX_CEIL_DIV(BlockHeight, CompressHeight);
791
792 BlockHeight = GetAligned3DBlockHeight(pTexInfo, BlockHeight, ExpandedArraySize);
793 }
794 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
795 {
796 BlockHeight /= 2;
797 }
798 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
799 {
800 BlockHeight /= 16;
801 }
802
803 BlockHeight *= ExpandedArraySize;
804 }
805 else
806 {
807 pTexInfo->Alignment.QPitch = 0;
808
809 BlockHeight = Get2DMipMapHeight(pTexInfo);
810 }
811
812 ///////////////////////////////////
813 // Calculate Pitch
814 ///////////////////////////////////
815
816 AlignedWidth = __GMM_EXPAND_WIDTH(this, Width, HAlign, pTexInfo);
817
818 // Calculate special pitch case of small dimensions where LOD1 + LOD2 widths
819 // are greater than LOD0. e.g. dimensions 4x4 and MinPitch == 1
820 if((pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs) &&
821 (pTexInfo->Alignment.MipTailStartLod < 2))
822 {
823 // Do nothing -- all mips are in LOD0/LOD1, which is already width aligned.
824 }
825 else if(pTexInfo->MaxLod >= 2)
826 {
827 uint32_t AlignedWidthLod1, AlignedWidthLod2;
828
829 AlignedWidthLod1 = __GMM_EXPAND_WIDTH(this, Width >> 1, HAlign, pTexInfo);
830 AlignedWidthLod2 = __GMM_EXPAND_WIDTH(this, Width >> 2, HAlign, pTexInfo);
831
832 AlignedWidth = GFX_MAX(AlignedWidth, AlignedWidthLod1 + AlignedWidthLod2);
833 }
834
835 if(Compress)
836 {
837 AlignedWidth = GFX_CEIL_DIV(AlignedWidth, CompressWidth);
838 }
839 else if(pTexInfo->Flags.Gpu.SeparateStencil && pTexInfo->Flags.Info.TiledW)
840 {
841 AlignedWidth *= 2;
842 }
843 else if(pTexInfo->Flags.Gpu.CCS && pTexInfo->Flags.Gpu.__NonMsaaTileYCcs)
844 {
845 switch(pTexInfo->BitsPerPixel)
846 {
847 case 32:
848 AlignedWidth /= 8;
849 break;
850 case 64:
851 AlignedWidth /= 4;
852 break;
853 case 128:
854 AlignedWidth /= 2;
855 break;
856 default:
857 __GMM_ASSERT(0);
858 }
859 }
860 else if(pTexInfo->Flags.Gpu.ColorSeparation)
861 {
862 AlignedWidth *= pTexInfo->ArraySize;
863 __GMM_ASSERT(0 == (AlignedWidth % GMM_COLOR_SEPARATION_WIDTH_DIVISION));
864 AlignedWidth /= GMM_COLOR_SEPARATION_WIDTH_DIVISION;
865 }
866 else if(pTexInfo->Flags.Gpu.ColorSeparationRGBX)
867 {
868 AlignedWidth *= pTexInfo->ArraySize;
869 __GMM_ASSERT(0 == (AlignedWidth % GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION));
870 AlignedWidth /= GMM_COLOR_SEPARATION_RGBX_WIDTH_DIVISION;
871 }
872
873 // Default pitch
874 Pitch = AlignedWidth * BitsPerPixel >> 3;
875
876 // Make sure the pitch satisfy linear min pitch requirment
877 Pitch = GFX_MAX(Pitch, pRestrictions->MinPitch);
878
879 // Make sure pitch satisfy alignment restriction
880 Pitch = GFX_ALIGN(Pitch, pRestrictions->PitchAlignment);
881
882 ////////////////////
883 // Adjust for Tiling
884 ////////////////////
885
886 if(GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]))
887 {
888 Pitch = GFX_ALIGN(Pitch, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileWidth);
889 BlockHeight = GFX_ALIGN(BlockHeight, pPlatform->TileInfo[pTexInfo->TileMode].LogicalTileHeight);
890 }
891
892 GMM_ASSERTDPF(pTexInfo->Flags.Info.LayoutBelow || !pTexInfo->Flags.Info.LayoutRight, "MIPLAYOUT_RIGHT not supported after Gen6!");
893 pTexInfo->Flags.Info.LayoutBelow = 1;
894 pTexInfo->Flags.Info.LayoutRight = 0;
895
896 // If a texture is YUV packed, 96, or 48 bpp then one row plus 16 bytes of
897 // padding needs to be added. Since this will create a none pitch aligned
898 // surface the padding is aligned to the next row
899 if(GmmIsYUVPacked(pTexInfo->Format) ||
900 (pTexInfo->BitsPerPixel == GMM_BITS(96)) ||
901 (pTexInfo->BitsPerPixel == GMM_BITS(48)))
902 {
903 BlockHeight += GMM_SCANLINES(1) + GFX_CEIL_DIV(GMM_BYTES(16), Pitch);
904 }
905
906 // Align height to even row to cover for HW over-fetch
907 BlockHeight = GFX_ALIGN(BlockHeight, __GMM_EVEN_ROW);
908
909 if((Status = // <-- Note assignment.
910 FillTexPitchAndSize(
911 pTexInfo, Pitch, BlockHeight, pRestrictions)) == GMM_SUCCESS)
912 {
913 Fill2DTexOffsetAddress(pTexInfo);
914 }
915
916 GMM_DPF_EXIT;
917
918 return (Status);
919 }
920
921
922 /////////////////////////////////////////////////////////////////////////////////////
923 /// Returns the mip offset of given LOD in Mip Tail
924 ///
925 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
926 /// MipLevel: given LOD #
927 ///
928 /// @return offset value of LOD in bytes
929 /////////////////////////////////////////////////////////////////////////////////////
GetMipTailByteOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel)930 uint32_t GmmLib::GmmGen9TextureCalc::GetMipTailByteOffset(GMM_TEXTURE_INFO *pTexInfo,
931 uint32_t MipLevel)
932 {
933 uint32_t ByteOffset = 0, Slot;
934
935 GMM_DPF_ENTER;
936
937 if((pTexInfo->Type == RESOURCE_1D) || (pTexInfo->Type == RESOURCE_3D))
938 {
939 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
940 (pTexInfo->Flags.Info.TiledYf ? 4 : 0);
941
942 switch(Slot)
943 {
944 case 0:
945 ByteOffset = GMM_KBYTE(32);
946 break;
947 case 1:
948 ByteOffset = GMM_KBYTE(16);
949 break;
950 case 2:
951 ByteOffset = GMM_KBYTE(8);
952 break;
953 case 3:
954 ByteOffset = GMM_KBYTE(4);
955 break;
956 case 4:
957 ByteOffset = GMM_KBYTE(2);
958 break;
959 case 5:
960 ByteOffset = GMM_KBYTE(1);
961 break;
962 case 6:
963 ByteOffset = GMM_BYTES(768);
964 break;
965 case 7:
966 ByteOffset = GMM_BYTES(512);
967 break;
968 case 8:
969 ByteOffset = GMM_BYTES(448);
970 break;
971 case 9:
972 ByteOffset = GMM_BYTES(384);
973 break;
974 case 10:
975 ByteOffset = GMM_BYTES(320);
976 break;
977 case 11:
978 ByteOffset = GMM_BYTES(256);
979 break;
980 case 12:
981 ByteOffset = GMM_BYTES(192);
982 break;
983 case 13:
984 ByteOffset = GMM_BYTES(128);
985 break;
986 case 14:
987 ByteOffset = GMM_BYTES(64);
988 break;
989 case 15:
990 ByteOffset = GMM_BYTES(0);
991 break;
992 default:
993 __GMM_ASSERT(0);
994 }
995 }
996 else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
997 {
998 // clang-format off
999 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
1000 // TileYs
1001 ((pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 16) ? 4 :
1002 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 8) ? 3 :
1003 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 4) ? 2 :
1004 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 2) ? 1 :
1005 (pTexInfo->Flags.Info.TiledYs ) ? 0 :
1006 // TileYf
1007 (pTexInfo->Flags.Info.TiledYf ) ? 4: 0);
1008 // clang-format on
1009
1010 switch(Slot)
1011 {
1012 case 0:
1013 ByteOffset = GMM_KBYTE(32);
1014 break;
1015 case 1:
1016 ByteOffset = GMM_KBYTE(16);
1017 break;
1018 case 2:
1019 ByteOffset = GMM_KBYTE(8);
1020 break;
1021 case 3:
1022 ByteOffset = GMM_KBYTE(4);
1023 break;
1024 case 4:
1025 ByteOffset = GMM_KBYTE(2);
1026 break;
1027 case 5:
1028 ByteOffset = GMM_BYTES(1536);
1029 break;
1030 case 6:
1031 ByteOffset = GMM_BYTES(1280);
1032 break;
1033 case 7:
1034 ByteOffset = GMM_BYTES(1024);
1035 break;
1036 case 8:
1037 ByteOffset = GMM_BYTES(768);
1038 break;
1039 case 9:
1040 ByteOffset = GMM_BYTES(512);
1041 break;
1042 case 10:
1043 ByteOffset = GMM_BYTES(256);
1044 break;
1045 case 11:
1046 ByteOffset = GMM_BYTES(192);
1047 break;
1048 case 12:
1049 ByteOffset = GMM_BYTES(128);
1050 break;
1051 case 13:
1052 ByteOffset = GMM_BYTES(64);
1053 break;
1054 case 14:
1055 ByteOffset = GMM_BYTES(0);
1056 break;
1057 default:
1058 __GMM_ASSERT(0);
1059 }
1060 }
1061
1062 GMM_DPF_EXIT;
1063
1064 return (ByteOffset);
1065 }
1066
1067 GMM_MIPTAIL_SLOT_OFFSET Gen9MipTailSlotOffset1DSurface[16][5] = GEN9_MIPTAIL_SLOT_OFFSET_1D_SURFACE;
1068 GMM_MIPTAIL_SLOT_OFFSET Gen9MipTailSlotOffset2DSurface[15][5] = GEN9_MIPTAIL_SLOT_OFFSET_2D_SURFACE;
1069 GMM_MIPTAIL_SLOT_OFFSET Gen9MipTailSlotOffset3DSurface[16][5] = GEN9_MIPTAIL_SLOT_OFFSET_3D_SURFACE;
1070 /////////////////////////////////////////////////////////////////////////////////////
1071 /// Returns the mip-map offset in geometric OffsetX, Y, Z
1072 // for a given LOD in Mip Tail.
1073 ///
1074 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
1075 /// MipLevel: mip-map level
1076 /// OffsetX: ptr to Offset in X direction (in bytes)
1077 /// OffsetY: ptr to Offset in Y direction (in pixels)
1078 /// OffsetZ: ptr to Offset in Z direction (in pixels)
1079 ///
1080 /////////////////////////////////////////////////////////////////////////////////////
GetMipTailGeometryOffset(GMM_TEXTURE_INFO * pTexInfo,uint32_t MipLevel,uint32_t * OffsetX,uint32_t * OffsetY,uint32_t * OffsetZ)1081 void GmmLib::GmmGen9TextureCalc::GetMipTailGeometryOffset(GMM_TEXTURE_INFO *pTexInfo,
1082 uint32_t MipLevel,
1083 uint32_t * OffsetX,
1084 uint32_t * OffsetY,
1085 uint32_t * OffsetZ)
1086 {
1087 uint32_t ArrayIndex = 0;
1088 uint32_t Slot = 0;
1089
1090 GMM_DPF_ENTER;
1091
1092 switch(pTexInfo->BitsPerPixel)
1093 {
1094 case 128:
1095 ArrayIndex = 0;
1096 break;
1097 case 64:
1098 ArrayIndex = 1;
1099 break;
1100 case 32:
1101 ArrayIndex = 2;
1102 break;
1103 case 16:
1104 ArrayIndex = 3;
1105 break;
1106 case 8:
1107 ArrayIndex = 4;
1108 break;
1109 default:
1110 __GMM_ASSERT(0);
1111 break;
1112 }
1113
1114 if(pTexInfo->Type == RESOURCE_1D)
1115 {
1116 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
1117 (pTexInfo->Flags.Info.TiledYf ? 4 : 0);
1118
1119 *OffsetX = Gen9MipTailSlotOffset1DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1120 *OffsetY = Gen9MipTailSlotOffset1DSurface[Slot][ArrayIndex].Y;
1121 *OffsetZ = Gen9MipTailSlotOffset1DSurface[Slot][ArrayIndex].Z;
1122 }
1123 else if(pTexInfo->Type == RESOURCE_2D || pTexInfo->Type == RESOURCE_CUBE)
1124 {
1125 // clang-format off
1126 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
1127 // TileYs
1128 ((pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 16) ? 4 :
1129 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 8) ? 3 :
1130 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 4) ? 2 :
1131 (pTexInfo->Flags.Info.TiledYs && pTexInfo->MSAA.NumSamples == 2) ? 1 :
1132 (pTexInfo->Flags.Info.TiledYs ) ? 0 :
1133 // TileYf
1134 (pTexInfo->Flags.Info.TiledYf ) ? 4: 0);
1135 // clang-format on
1136
1137 *OffsetX = Gen9MipTailSlotOffset2DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1138 *OffsetY = Gen9MipTailSlotOffset2DSurface[Slot][ArrayIndex].Y;
1139 *OffsetZ = Gen9MipTailSlotOffset2DSurface[Slot][ArrayIndex].Z;
1140 }
1141 else if(pTexInfo->Type == RESOURCE_3D)
1142 {
1143 Slot = MipLevel - pTexInfo->Alignment.MipTailStartLod +
1144 (pTexInfo->Flags.Info.TiledYf ? 4 : 0);
1145
1146 *OffsetX = Gen9MipTailSlotOffset3DSurface[Slot][ArrayIndex].X * pTexInfo->BitsPerPixel / 8;
1147 *OffsetY = Gen9MipTailSlotOffset3DSurface[Slot][ArrayIndex].Y;
1148 *OffsetZ = Gen9MipTailSlotOffset3DSurface[Slot][ArrayIndex].Z;
1149 }
1150
1151 GMM_DPF_EXIT;
1152 return;
1153 }
1154
1155
1156 /////////////////////////////////////////////////////////////////////////////////////
1157 /// Allocates the 3D mip layout for surface state programming.
1158 ///
1159 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
1160 /// @param[in] pRestrictions: ptr to surface alignment and size restrictions
1161 ///
1162 /// @return ::GMM_STATUS
1163 /////////////////////////////////////////////////////////////////////////////////////
FillTex3D(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)1164 GMM_STATUS GMM_STDCALL GmmLib::GmmGen9TextureCalc::FillTex3D(GMM_TEXTURE_INFO * pTexInfo,
1165 __GMM_BUFFER_TYPE *pRestrictions)
1166 {
1167 return FillTex2D(pTexInfo, pRestrictions);
1168 }
1169
1170
1171 /////////////////////////////////////////////////////////////////////////////////////
1172 /// Calculates the cube layout for surface state programming.
1173 ///
1174 /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO,
1175 /// @param[in] pRestrictions: ptr to surface alignment and size restrictions
1176 ///
1177 /// @return ::GMM_STATUS
1178 /////////////////////////////////////////////////////////////////////////////////////
FillTexCube(GMM_TEXTURE_INFO * pTexInfo,__GMM_BUFFER_TYPE * pRestrictions)1179 GMM_STATUS GMM_STDCALL GmmLib::GmmGen9TextureCalc::FillTexCube(GMM_TEXTURE_INFO * pTexInfo,
1180 __GMM_BUFFER_TYPE *pRestrictions)
1181 {
1182 return FillTex2D(pTexInfo, pRestrictions);
1183 }
1184
1185 /////////////////////////////////////////////////////////////////////////////////////
1186 /// This function does any special-case conversion from client-provided pseudo creation
1187 /// parameters to actual parameters for CCS.
1188 ///
1189 /// @param[in] pTexInfo: Reference to ::GMM_TEXTURE_INFO
1190 ///
1191 /// @return ::GMM_STATUS
1192 /////////////////////////////////////////////////////////////////////////////////////
MSAACCSUsage(GMM_TEXTURE_INFO * pTexInfo)1193 GMM_STATUS GMM_STDCALL GmmLib::GmmGen9TextureCalc::MSAACCSUsage(GMM_TEXTURE_INFO *pTexInfo)
1194 {
1195 GMM_STATUS Status = GMM_SUCCESS;
1196
1197 if(pTexInfo->MSAA.NumSamples > 1) // CCS for MSAA Compression
1198 {
1199 Status = MSAACompression(pTexInfo);
1200 }
1201 else // Non-MSAA CCS Use (i.e. Render Target Fast Clear)
1202 {
1203 if(!pTexInfo->Flags.Info.TiledW &&
1204 (!pTexInfo->Flags.Info.TiledX) &&
1205 ((!pTexInfo->Flags.Info.Linear) ||
1206 (GMM_IS_4KB_TILE(pTexInfo->Flags) || GMM_IS_64KB_TILE(pTexInfo->Flags) ||
1207 (pTexInfo->Type == RESOURCE_BUFFER && pTexInfo->Flags.Info.Linear))) && //!Yf - deprecate Yf
1208 ((pTexInfo->BitsPerPixel == 32) ||
1209 (pTexInfo->BitsPerPixel == 64) ||
1210 (pTexInfo->BitsPerPixel == 128)))
1211 {
1212 // For non-MSAA CCS usage, the four tables of
1213 // requirements:
1214 // (1) RT Alignment (GMM Don't Care: Occurs Naturally)
1215 // (2) ClearRect Alignment
1216 // (3) ClearRect Scaling (GMM Don't Care: GHAL3D Matter)
1217 // (4) Non-MSAA CCS Sizing
1218
1219 // Gen8+:
1220 // Since mip-mapped and arrayed surfaces are supported, we
1221 // deal with alignment later at per mip level. Here, we set
1222 // tiling type only. TileX is not supported on Gen9+.
1223 // Pre-Gen8:
1224 // (!) For all the above, there are separate entries for
1225 // 32/64/128bpp--and then deals with PIXEL widths--Here,
1226 // though, we will unify by considering 8bpp table entries
1227 // (unlisted--i.e. do the math)--and deal with BYTE widths.
1228
1229 // (1) RT Alignment -- The surface width and height don't
1230 // need to be padded to RT CL granularity. On HSW, all tiled
1231 // RT's will have appropriate alignment (given 4KB surface
1232 // base and no mip-map support) and appropriate padding
1233 // (due to tile padding). On BDW+, GMM uses H/VALIGN that
1234 // will guarantee the MCS RT alignment for all subresources.
1235
1236 // (2) ClearRect Alignment -- I.e. FastClears must be done
1237 // with certain granularity:
1238 // TileY: 512 Bytes x 128 Lines
1239 // TileX: 1024 Bytes x 64 Lines
1240 // So a CCS must be sized to match that granularity (though
1241 // the RT itself need not be fully padded to that
1242 // granularity to use FastClear).
1243
1244 // (4) Non-MSAA CCS Sizing -- CCS sizing is based on the
1245 // size of the FastClear (with granularity padding) for the
1246 // paired RT. CCS's (byte widths and heights) are scaled
1247 // down from their RT's by:
1248 // TileY: 32 x 32
1249 // TileX: 64 x 16
1250
1251 // ### Example #############################################
1252 // RT: 800x600, 32bpp, TileY
1253 // 8bpp: 3200x600
1254 // FastClear: 3584x640 (for TileY FastClear Granularity of 512x128)
1255 // CCS: 112x20 (for TileY RT:CCS Sizing Downscale of 32x32)
1256
1257 pTexInfo->Flags.Gpu.__NonMsaaTileYCcs = pTexInfo->Flags.Info.TiledY || pTexInfo->Flags.Info.TiledYf || pTexInfo->Flags.Info.TiledYs;
1258 pTexInfo->Flags.Gpu.__NonMsaaTileXCcs = pTexInfo->Flags.Info.TiledX;
1259 }
1260 else
1261 {
1262 GMM_ASSERTDPF(0, "Illegal CCS creation parameters!");
1263 Status = GMM_ERROR;
1264 }
1265 }
1266 return Status;
1267 }
1268