| /*============================================================================== |
| Copyright(c) 2017 Intel Corporation |
| |
| Permission is hereby granted, free of charge, to any person obtaining a |
| copy of this software and associated documentation files(the "Software"), |
| to deal in the Software without restriction, including without limitation |
| the rights to use, copy, modify, merge, publish, distribute, sublicense, |
| and / or sell copies of the Software, and to permit persons to whom the |
| Software is furnished to do so, subject to the following conditions: |
| |
| The above copyright notice and this permission notice shall be included |
| in all copies or substantial portions of the Software. |
| |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
| THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR |
| OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, |
| ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
| OTHER DEALINGS IN THE SOFTWARE. |
| ============================================================================*/ |
| |
| #include "Internal/Common/GmmLibInc.h" |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Checks that clients only set Presentable flag during a resource allocation, ONLY |
| /// when a platform supported render target is selected in ::GMM_RESOURCE_FORMAT enum. |
| /// |
| /// @return true if displayable, false otherwise. |
| ///////////////////////////////////////////////////////////////////////////////////// |
| bool GmmLib::GmmResourceInfoCommon::IsPresentableformat() |
| { |
| const GMM_PLATFORM_INFO *pPlatform; |
| const GMM_FORMAT_ENTRY * FormatTable = NULL; |
| |
| GMM_DPF_ENTER; |
| __GMM_ASSERTPTR(pGmmGlobalContext, false); |
| |
| pPlatform = GMM_OVERRIDE_PLATFORM_INFO(&Surf); |
| FormatTable = &(pPlatform->FormatTable[0]); |
| |
| if(Surf.Flags.Gpu.Presentable == false) |
| { |
| // When Presentable flag is not set, no reason to check for valid RT |
| // platform supported format. Safe to return true. |
| return true; |
| } |
| |
| if((Surf.Format > GMM_FORMAT_INVALID) && |
| (Surf.Format < GMM_RESOURCE_FORMATS)) |
| { |
| if((FormatTable[Surf.Format].RenderTarget) && |
| (FormatTable[Surf.Format].Supported)) |
| { |
| return true; |
| } |
| else |
| { |
| GMM_ASSERTDPF(0, "Present flag can only be set w/ a format!"); |
| return false; |
| } |
| } |
| |
| return false; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Returns the restrictions that a particular resource must follow on a particular |
| /// OS or hardware. |
| /// |
| /// @param[out] Restrictions: restrictions that this resource must adhere to |
| ///////////////////////////////////////////////////////////////////////////////////// |
| void GmmLib::GmmResourceInfoCommon::GetRestrictions(__GMM_BUFFER_TYPE &Restrictions) |
| { |
| GMM_DPF_ENTER; |
| |
| GMM_TEXTURE_CALC *pTextureCalc = NULL; |
| pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(&Surf); |
| pTextureCalc->GetResRestrictions(&Surf, Restrictions); |
| |
| GMM_DPF_EXIT; |
| } |
| |
| |
| //============================================================================= |
| // |
| // Function: GmmResGetRestrictions |
| // |
| // Desc: This routine returns resource restrictions |
| // |
| // Parameters: |
| // pPlatform: ptr to HW_DEVICE_EXTENSION |
| // pResourceInfo: ptr to GMM_RESOURCE_INFO |
| // pRestrictions: ptr to restrictions |
| // |
| // Returns: |
| // void |
| // |
| //----------------------------------------------------------------------------- |
| void GMM_STDCALL GmmResGetRestrictions(GMM_RESOURCE_INFO *pResourceInfo, |
| __GMM_BUFFER_TYPE *pRestrictions) |
| { |
| pResourceInfo->GetRestrictions(*pRestrictions); |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Returns the best restrictions by comparing two buffer types. Each buffer type |
| /// carries alignment and size restrictions. |
| /// |
| /// @param[in] pFirstBuffer: Contains surface alignment and size restrictions |
| /// @param[in] pSecondBuffer: Contains surface alignment and size restrictions |
| /// |
| /// @return Best Restrictions based on the two parameters passed |
| ///////////////////////////////////////////////////////////////////////////////////// |
| __GMM_BUFFER_TYPE *GmmLib::GmmTextureCalc::GetBestRestrictions(__GMM_BUFFER_TYPE * pFirstBuffer, |
| const __GMM_BUFFER_TYPE *pSecondBuffer) |
| { |
| GMM_DPF_ENTER; |
| |
| if(IsRestrictionInvalid(pFirstBuffer)) //default |
| { |
| *pFirstBuffer = *pSecondBuffer; |
| return pFirstBuffer; |
| } |
| |
| pFirstBuffer->Alignment = GFX_MAX(pFirstBuffer->Alignment, |
| pSecondBuffer->Alignment); |
| |
| pFirstBuffer->PitchAlignment = GFX_MAX(pFirstBuffer->PitchAlignment, |
| pSecondBuffer->PitchAlignment); |
| |
| pFirstBuffer->RenderPitchAlignment = GFX_MAX(pFirstBuffer->RenderPitchAlignment, |
| pSecondBuffer->RenderPitchAlignment); |
| |
| pFirstBuffer->LockPitchAlignment = GFX_MAX(pFirstBuffer->LockPitchAlignment, |
| pSecondBuffer->LockPitchAlignment); |
| |
| pFirstBuffer->MinPitch = GFX_MAX(pFirstBuffer->MinPitch, |
| pSecondBuffer->MinPitch); |
| |
| pFirstBuffer->MinAllocationSize = GFX_MAX(pFirstBuffer->MinAllocationSize, |
| pSecondBuffer->MinAllocationSize); |
| |
| pFirstBuffer->MinDepth = GFX_MAX(pFirstBuffer->MinDepth, |
| pSecondBuffer->MinDepth); |
| |
| pFirstBuffer->MinHeight = GFX_MAX(pFirstBuffer->MinHeight, |
| pSecondBuffer->MinHeight); |
| |
| pFirstBuffer->MinWidth = GFX_MAX(pFirstBuffer->MinWidth, |
| pSecondBuffer->MinWidth); |
| |
| pFirstBuffer->MaxDepth = GFX_MIN(pFirstBuffer->MaxDepth, |
| pSecondBuffer->MaxDepth); |
| |
| pFirstBuffer->MaxHeight = GFX_MIN(pFirstBuffer->MaxHeight, |
| pSecondBuffer->MaxHeight); |
| |
| pFirstBuffer->MaxWidth = GFX_MIN(pFirstBuffer->MaxWidth, |
| pSecondBuffer->MaxWidth); |
| |
| pFirstBuffer->NeedPow2LockAlignment = pFirstBuffer->NeedPow2LockAlignment | |
| pSecondBuffer->NeedPow2LockAlignment; |
| |
| GMM_DPF_EXIT; |
| return pFirstBuffer; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Returns restrictions for 1D, 2D, 3D textures depending on how the surface |
| /// may possibliy be used. |
| /// |
| /// @param[out] pBuff: Restrictions filled in this struct |
| ///////////////////////////////////////////////////////////////////////////////////// |
| void GmmLib::GmmTextureCalc::GetGenericRestrictions(GMM_TEXTURE_INFO *pTexInfo, __GMM_BUFFER_TYPE *pBuff) |
| { |
| GMM_DPF_ENTER; |
| const GMM_PLATFORM_INFO *pPlatformResource = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo); |
| |
| if(pTexInfo->Flags.Gpu.NoRestriction) |
| { |
| // Impose zero restrictions. Ignore any other GPU usage flags |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->NoRestriction); |
| return; |
| } |
| |
| if(pTexInfo->Flags.Gpu.Texture) |
| { |
| if(pTexInfo->Type == RESOURCE_BUFFER) |
| { |
| *pBuff = pPlatformResource->BufferType; |
| } |
| else if(pTexInfo->Type == RESOURCE_CUBE) |
| { |
| *pBuff = pPlatformResource->CubeSurface; |
| } |
| else if(pTexInfo->Type == RESOURCE_3D) |
| { |
| *pBuff = pPlatformResource->Texture3DSurface; |
| } |
| else |
| { |
| *pBuff = pPlatformResource->Texture2DSurface; |
| if(pTexInfo->Flags.Info.Linear) |
| { |
| *pBuff = pPlatformResource->Texture2DLinearSurface; |
| } |
| if(GmmIsReconstructableSurface(pTexInfo->Format)) |
| { |
| pBuff->MaxHeight = pPlatformResource->ReconMaxHeight; |
| pBuff->MaxWidth = pPlatformResource->ReconMaxWidth; |
| } |
| } |
| } |
| if(pTexInfo->Flags.Gpu.RenderTarget || |
| pTexInfo->Flags.Gpu.CCS || |
| pTexInfo->Flags.Gpu.MCS) |
| { |
| // Gen7 onwards, bound by SURFACE_STATE constraints. |
| if(pTexInfo->Type == RESOURCE_BUFFER) |
| { |
| *pBuff = pPlatformResource->BufferType; |
| } |
| else if(pTexInfo->Type == RESOURCE_CUBE) |
| { |
| *pBuff = pPlatformResource->CubeSurface; |
| } |
| else if(pTexInfo->Type == RESOURCE_3D) |
| { |
| *pBuff = pPlatformResource->Texture3DSurface; |
| } |
| else |
| { |
| *pBuff = pPlatformResource->Texture2DSurface; |
| if(pTexInfo->Flags.Info.Linear) |
| { |
| *pBuff = pPlatformResource->Texture2DLinearSurface; |
| } |
| if(GmmIsReconstructableSurface(pTexInfo->Format)) |
| { |
| pBuff->MaxHeight = pPlatformResource->ReconMaxHeight; |
| pBuff->MaxWidth = pPlatformResource->ReconMaxWidth; |
| } |
| } |
| } |
| if(pTexInfo->Flags.Gpu.Depth) |
| { |
| // Z |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Depth); |
| } |
| if(pTexInfo->Flags.Gpu.Vertex) |
| { |
| // VertexData |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Vertex); |
| } |
| if(pTexInfo->Flags.Gpu.Index) |
| { |
| // Index buffer |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Index); |
| } |
| if(pTexInfo->Flags.Gpu.FlipChain) |
| { |
| // Async Flip |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->ASyncFlipSurface); |
| } |
| if(pTexInfo->Flags.Gpu.MotionComp) |
| { |
| // Media buffer |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->MotionComp); |
| } |
| if(pTexInfo->Flags.Gpu.State || |
| pTexInfo->Flags.Gpu.InstructionFlat || |
| pTexInfo->Flags.Gpu.ScratchFlat) |
| { |
| // indirect state |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Vertex); |
| } |
| if(pTexInfo->Flags.Gpu.Query || |
| pTexInfo->Flags.Gpu.HistoryBuffer) |
| { |
| // Query |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->NoRestriction); |
| } |
| if(pTexInfo->Flags.Gpu.Constant) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Constant); |
| } |
| if(pTexInfo->Flags.Gpu.Stream) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Stream); |
| } |
| if(pTexInfo->Flags.Gpu.InterlacedScan) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->InterlacedScan); |
| } |
| if(pTexInfo->Flags.Gpu.TextApi) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->TextApi); |
| } |
| if(pTexInfo->Flags.Gpu.SeparateStencil) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Stencil); |
| } |
| if(pTexInfo->Flags.Gpu.HiZ) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->HiZ); |
| } |
| if(pTexInfo->Flags.Gpu.Video) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Video); |
| if(GmmIsReconstructableSurface(pTexInfo->Format)) |
| { |
| pBuff->MaxHeight = pPlatformResource->ReconMaxHeight; |
| pBuff->MaxWidth = pPlatformResource->ReconMaxWidth; |
| } |
| } |
| if(pTexInfo->Flags.Gpu.StateDx9ConstantBuffer) |
| { |
| // |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->StateDx9ConstantBuffer); |
| } |
| if(pTexInfo->Flags.Gpu.Overlay) |
| { |
| // Overlay buffer use Async Flip values |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->Overlay); |
| |
| if((pTexInfo->Format == GMM_FORMAT_YUY2) && (pTexInfo->BaseWidth == 640)) |
| { |
| // override the pitch alignment |
| pBuff->PitchAlignment = 64; |
| } |
| } |
| if(pTexInfo->Flags.Info.XAdapter) |
| { |
| //Add Cross Adapter resource restriction for hybrid graphics. |
| pBuff = GetBestRestrictions(pBuff, &pPlatformResource->XAdapter); |
| if(pTexInfo->Type == RESOURCE_BUFFER) |
| { |
| pBuff->MaxWidth = pPlatformResource->SurfaceMaxSize; |
| pBuff->MaxPitch = pPlatformResource->BufferType.MaxPitch; |
| pBuff->MaxHeight = 1; |
| } |
| } |
| |
| //Non Aligned ExistingSysMem Special cases. |
| if((pTexInfo->Flags.Info.ExistingSysMem && |
| (!pTexInfo->ExistingSysMem.IsGmmAllocated) && |
| (!pTexInfo->ExistingSysMem.IsPageAligned))) |
| { |
| |
| if(pTexInfo->Flags.Info.Linear || |
| pTexInfo->Flags.Info.SVM) |
| { |
| if(pTexInfo->Type == RESOURCE_BUFFER) |
| { |
| //Use combination of BufferType, NoRestriction to support large buffer with minimal pitch alignment |
| *pBuff = pPlatformResource->BufferType; |
| pBuff->PitchAlignment = pPlatformResource->NoRestriction.PitchAlignment; |
| pBuff->LockPitchAlignment = pPlatformResource->NoRestriction.LockPitchAlignment; |
| pBuff->RenderPitchAlignment = pPlatformResource->NoRestriction.LockPitchAlignment; |
| pBuff->MinPitch = pPlatformResource->NoRestriction.MinPitch; |
| } |
| |
| //[To DO] Handle other types when needed! |
| } |
| /* |
| else if(Surf.Flags.Gpu.Texture) |
| { |
| //Override as and when required |
| } |
| else if(Surf.Flags.Gpu.RenderTarget) |
| { |
| //Overide as and when Required |
| }*/ |
| } |
| |
| GMM_DPF_EXIT; |
| } |
| |
| //============================================================================= |
| // |
| // Function: __GmmPlatformResetRestrictions |
| // |
| // Desc: This routine initializes a __GMM_BUFFER_TYPE. Once this function is |
| // called, the caller has a invalid restrictions. |
| // |
| // Parameters: |
| // pRestriction ==> Restrictions |
| // Returns: |
| // void |
| // |
| //----------------------------------------------------------------------------- |
| void __GmmPlatformResetRestrictions(__GMM_BUFFER_TYPE *pRestriction) |
| { |
| pRestriction->MinDepth = 0xffffffff; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Internal function resets the restrictions and puts the allocation in invalid state |
| /// |
| /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO, |
| /// @param[in] pRestrictions: reset the restrictions to invalid state. |
| /// |
| ///////////////////////////////////////////////////////////////////////////////////// |
| void GmmLib::GmmTextureCalc::ResetRestrictions(__GMM_BUFFER_TYPE *pRestriction) |
| { |
| pRestriction->MinDepth = 0xffffffff; |
| } |
| |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Internal function returns the best restrictions depending on how the surface may |
| /// possibly be used. |
| /// |
| /// @param[in] pTexInfo: ptr to ::GMM_TEXTURE_INFO, |
| /// @param[in] pRestrictions: Reference to surface alignment and size restrictions |
| /// |
| ///////////////////////////////////////////////////////////////////////////////////// |
| void GmmLib::GmmTextureCalc::GetTexRestrictions(GMM_TEXTURE_INFO * pTexInfo, |
| __GMM_BUFFER_TYPE *pRestrictions) |
| { |
| GMM_DPF_ENTER; |
| |
| GetResRestrictions(pTexInfo, *pRestrictions); |
| |
| GMM_DPF_EXIT; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Returns the restrictions that a particular resource must follow on a particular |
| /// OS or hardware. |
| /// |
| /// @param[out] Restrictions: restrictions that this resource must adhere to |
| ///////////////////////////////////////////////////////////////////////////////////// |
| void GmmLib::GmmTextureCalc::GetResRestrictions(GMM_TEXTURE_INFO * pTexinfo, |
| __GMM_BUFFER_TYPE &Restrictions) |
| { |
| GMM_DPF_ENTER; |
| const GMM_PLATFORM_INFO *pPlatform = NULL; |
| GMM_RESOURCE_FLAG ZeroGpuFlags; |
| |
| __GMM_ASSERTPTR(pGmmGlobalContext, VOIDRETURN); |
| |
| pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexinfo); |
| |
| // Check that at least one usage flag is set for allocations other than |
| // Primary/Shadow/Staging. |
| memset(&ZeroGpuFlags.Gpu, 0, sizeof(ZeroGpuFlags.Gpu)); |
| if((pTexinfo->Type <= RESOURCE_KMD_CHECK_START || |
| pTexinfo->Type >= RESOURCE_KMD_CHECK_END) && |
| !memcmp(&pTexinfo->Flags.Gpu, &ZeroGpuFlags.Gpu, sizeof(ZeroGpuFlags.Gpu))) |
| { |
| GMM_ASSERTDPF(0, "No GPU Usage specified!"); |
| return; |
| } |
| |
| ResetRestrictions(&Restrictions); //Set to Default |
| |
| // Get worst case restrictions that match GPU flags set in resource |
| switch(pTexinfo->Type) |
| { |
| case RESOURCE_1D: |
| case RESOURCE_2D: |
| case RESOURCE_3D: |
| case RESOURCE_CUBE: |
| case RESOURCE_BUFFER: |
| case RESOURCE_SCRATCH: |
| case RESOURCE_GDI: |
| GetGenericRestrictions(pTexinfo, &Restrictions); |
| break; |
| |
| case RESOURCE_HW_CONTEXT: |
| case RESOURCE_TAG_PAGE: |
| if(pTexinfo->Flags.Info.TiledW || |
| pTexinfo->Flags.Info.TiledX || |
| GMM_IS_4KB_TILE(pTexinfo->Flags)) |
| { |
| GMM_ASSERTDPF(0, "Tiled Pref specified for RESOURCE_LINEAR!"); |
| return; |
| } |
| GetLinearRestrictions(pTexinfo, &Restrictions); |
| break; |
| |
| case RESOURCE_PRIMARY: |
| case RESOURCE_SHADOW: |
| case RESOURCE_STAGING: |
| GetPrimaryRestrictions(pTexinfo, &Restrictions); |
| break; |
| |
| case RESOURCE_NNDI: |
| Restrictions = pPlatform->Nndi; |
| break; |
| |
| case RESOURCE_HARDWARE_MBM: |
| case RESOURCE_IFFS_MAPTOGTT: |
| //Hardware MBM resource request can come for overlay allocation or normal |
| //displayable allocation. So get the restrictions accordingly |
| if(pTexinfo->Flags.Gpu.Overlay) |
| { |
| Restrictions = pPlatform->Overlay; |
| } |
| else |
| { |
| Restrictions = pPlatform->HardwareMBM; |
| } |
| break; |
| |
| case RESOURCE_CURSOR: |
| case RESOURCE_PWR_CONTEXT: |
| case RESOURCE_KMD_BUFFER: |
| case RESOURCE_NULL_CONTEXT_INDIRECT_STATE: |
| case RESOURCE_PERF_DATA_QUEUE: |
| case RESOURCE_GLOBAL_BUFFER: |
| case RESOURCE_FBC: |
| case RESOURCE_GFX_CLIENT_BUFFER: |
| Restrictions = pPlatform->Cursor; |
| break; |
| |
| case RESOURCE_OVERLAY_DMA: |
| Restrictions = pPlatform->NoRestriction; |
| break; |
| |
| case RESOURCE_GTT_TRANSFER_REGION: |
| GetGenericRestrictions(pTexinfo, &Restrictions); |
| break; |
| |
| case RESOURCE_OVERLAY_INTERMEDIATE_SURFACE: |
| Restrictions = pPlatform->Overlay; |
| break; |
| |
| default: |
| GetGenericRestrictions(pTexinfo, &Restrictions); |
| GMM_ASSERTDPF(0, "Unkown Resource type"); |
| } |
| // Apply any specific WA |
| |
| if(((pTexinfo->Flags.Wa.ILKNeedAvcMprRowStore32KAlign)) || |
| ((pTexinfo->Flags.Wa.ILKNeedAvcDmvBuffer32KAlign))) |
| { |
| Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, GMM_KBYTE(32)); |
| } |
| |
| if(pGmmGlobalContext->GetWaTable().WaAlignContextImage && (pTexinfo->Type == RESOURCE_HW_CONTEXT)) |
| { |
| Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, GMM_KBYTE(64)); |
| } |
| |
| if(pTexinfo->Flags.Gpu.S3d && |
| pTexinfo->Flags.Info.Linear && |
| !pGmmGlobalContext->GetSkuTable().FtrDisplayEngineS3d) |
| { |
| Restrictions.Alignment = PAGE_SIZE; |
| Restrictions.PitchAlignment = PAGE_SIZE; |
| } |
| |
| if(pTexinfo->Flags.Gpu.TiledResource) |
| { |
| // Need at least 64KB alignment to track tile mappings (h/w or s/w tracking). |
| Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, GMM_KBYTE(64)); |
| |
| // Buffer tiled resources are trivially divided into 64KB tiles => Pitch must divide into 64KB tiles |
| if(pTexinfo->Type == RESOURCE_BUFFER) |
| { |
| Restrictions.PitchAlignment = GFX_ALIGN(Restrictions.PitchAlignment, GMM_KBYTE(64)); |
| } |
| |
| if(GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) >= IGFX_GEN9_CORE) |
| { |
| pGmmGlobalContext->GetPlatformInfo().SurfaceMaxSize = GMM_TBYTE(1); |
| } |
| } |
| |
| // SKL TileY Display needs 1MB alignment. |
| if(((pTexinfo->Type == RESOURCE_PRIMARY) || |
| pTexinfo->Flags.Gpu.FlipChain) && |
| (GMM_IS_4KB_TILE(pTexinfo->Flags) || |
| pTexinfo->Flags.Info.TiledYf)) |
| { |
| Restrictions.Alignment = GMM_MBYTE(1); |
| } |
| |
| if(pTexinfo->Flags.Info.RenderCompressed || |
| pTexinfo->Flags.Info.MediaCompressed) |
| { |
| if(pGmmGlobalContext->GetSkuTable().FtrFlatPhysCCS) |
| { |
| Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, GMM_KBYTE(64)); |
| } |
| else // only for platforms having auxtable |
| { |
| Restrictions.Alignment = GFX_ALIGN(Restrictions.Alignment, (!WA16K ? GMM_KBYTE(64) : GMM_KBYTE(16))); |
| } |
| } |
| |
| GMM_DPF_EXIT; |
| } |
| |
| ///////////////////////////////////////////////////////////////////////////////////// |
| /// Calculates surface size based on Non Aligned ExistingSysMem restrictions. |
| /// |
| /// @return ::GMM_STATUS |
| ///////////////////////////////////////////////////////////////////////////////////// |
| GMM_STATUS GmmLib::GmmResourceInfoCommon::ApplyExistingSysMemRestrictions() |
| { |
| const GMM_PLATFORM_INFO *pPlatform; |
| |
| // Handle Minimal Restriction ExistingSysMem Requirements... |
| GMM_GFX_SIZE_T AdditionalPaddingBytes = 0; |
| GMM_GFX_SIZE_T AdditionalPaddingRows = 0; |
| GMM_GFX_SIZE_T BaseAlignment = 1; // 1 = Byte Alignment |
| GMM_GFX_SIZE_T EndAlignment = 1; // 1 = Byte Alignment |
| GMM_GFX_SIZE_T SizePadding = 1; // 1 = Byte Padding |
| uint32_t CompressHeight, CompressWidth, CompressDepth; |
| GMM_GFX_SIZE_T Width, Height; |
| GMM_TEXTURE_INFO *pTexInfo = &Surf; |
| GMM_TEXTURE_CALC *pTextureCalc; |
| |
| GMM_DPF_ENTER; |
| |
| pPlatform = GMM_OVERRIDE_PLATFORM_INFO(pTexInfo); |
| pTextureCalc = GMM_OVERRIDE_TEXTURE_CALC(pTexInfo); |
| |
| Height = pTexInfo->BaseHeight; |
| Width = pTexInfo->BaseWidth; |
| |
| #define UPDATE_BASE_ALIGNMENT(a) \ |
| { \ |
| __GMM_ASSERT((GFX_MAX(BaseAlignment, a) % GFX_MIN(BaseAlignment, a)) == 0); /* Revisit if ever have to support complex alignments. */ \ |
| BaseAlignment = GFX_MAX(BaseAlignment, a); \ |
| } |
| |
| #define UPDATE_PADDING(p) \ |
| { \ |
| SizePadding = GFX_MAX(SizePadding, p); \ |
| } |
| |
| #define UPDATE_ADDITIONAL_ROWS(r) \ |
| { \ |
| AdditionalPaddingRows = GFX_MAX(AdditionalPaddingRows, r); \ |
| } |
| |
| #define UPDATE_ADDITIONAL_BYTES(b) \ |
| { \ |
| AdditionalPaddingBytes = GFX_MAX(AdditionalPaddingBytes, b); \ |
| } |
| |
| #define UPDATE_END_ALIGNMENT(a) \ |
| { \ |
| __GMM_ASSERT((GFX_MAX(EndAlignment, a) % GFX_MIN(EndAlignment, a)) == 0); /* Revisit if ever have to support complex alignments. */ \ |
| EndAlignment = GFX_MAX(EndAlignment, a); \ |
| } |
| |
| |
| if(!pTexInfo->Pitch) |
| { |
| __GMM_ASSERT(pTexInfo->Type == RESOURCE_1D); // Clients can leave pitch zero for 1D, and we'll fill-in... |
| pTexInfo->Pitch = Width * (pTexInfo->BitsPerPixel >> 3); |
| } |
| |
| __GMM_ASSERT( // Currently limiting our support... |
| pTexInfo->Flags.Gpu.NoRestriction || |
| pTexInfo->Flags.Gpu.Index || |
| pTexInfo->Flags.Gpu.RenderTarget || |
| pTexInfo->Flags.Gpu.Texture || |
| pTexInfo->Flags.Gpu.Vertex); |
| |
| __GMM_ASSERT( // Trivial, Linear Surface... |
| ((pTexInfo->Type == RESOURCE_BUFFER) || (pTexInfo->Type == RESOURCE_1D) || (pTexInfo->Type == RESOURCE_2D)) && |
| (pTexInfo->MaxLod == 0) && |
| !GMM_IS_TILED(pPlatform->TileInfo[pTexInfo->TileMode]) && |
| !GmmIsPlanar(pTexInfo->Format) && |
| ((pTexInfo->ArraySize <= 1) || (pTexInfo->Type == RESOURCE_BUFFER))); |
| |
| __GMM_ASSERT( // Valid Surface... |
| (Width > 0) && |
| !((pTexInfo->Type == RESOURCE_BUFFER) && GmmIsYUVPacked(pTexInfo->Format))); |
| |
| // Convert to compression blocks, if applicable... |
| if(GmmIsCompressed(pTexInfo->Format)) |
| { |
| pTextureCalc->GetCompressionBlockDimensions(pTexInfo->Format, &CompressWidth, &CompressHeight, &CompressDepth); |
| |
| Width = GFX_CEIL_DIV(Width, CompressWidth); |
| Height = GFX_CEIL_DIV(Height, CompressHeight); |
| } |
| |
| __GMM_ASSERT( // Valid Surface Follow-Up... |
| (pTexInfo->Pitch >= (Width * (pTexInfo->BitsPerPixel >> 3)))); |
| |
| if(!pTexInfo->Flags.Gpu.NoRestriction && !pTexInfo->Flags.Info.SVM && !pTexInfo->Flags.Info.Linear) |
| { |
| if(pTexInfo->Flags.Gpu.Index) ///////////////////////////////////////////////////////// |
| { |
| __GMM_ASSERT(!( |
| pTexInfo->Flags.Gpu.RenderTarget || |
| pTexInfo->Flags.Gpu.Texture || |
| pTexInfo->Flags.Gpu.Vertex)); // Can explore if needed what combo's make sense--and how req's should combine. |
| |
| // 3DSTATE_INDEX_BUFFER... |
| UPDATE_BASE_ALIGNMENT(4); // 32-bit worst-case, since GMM doesn't receive element-size from clients. |
| if(pGmmGlobalContext->GetWaTable().WaAlignIndexBuffer) |
| { |
| UPDATE_END_ALIGNMENT(64); |
| } |
| else |
| { |
| UPDATE_END_ALIGNMENT(1); |
| } |
| } |
| |
| if(pTexInfo->Flags.Gpu.Vertex) //////////////////////////////////////////////////////// |
| { |
| __GMM_ASSERT(!( |
| pTexInfo->Flags.Gpu.Index || |
| pTexInfo->Flags.Gpu.RenderTarget || |
| pTexInfo->Flags.Gpu.Texture)); // Can explore if needed what combo's make sense--and how req's should combine. |
| |
| // VERTEX_BUFFER_STATE... |
| UPDATE_BASE_ALIGNMENT(1); // VB's have member alignment requirements--but it's up to UMD to enforce. |
| UPDATE_PADDING(1); |
| } |
| |
| if(pTexInfo->Flags.Gpu.RenderTarget) ////////////////////////////////////////////////// |
| { |
| uint32_t ElementSize; |
| |
| // SURFACE_STATE... |
| ElementSize = (pTexInfo->BitsPerPixel >> 3) * (GmmIsYUVPacked(pTexInfo->Format) ? 2 : 1); |
| __GMM_ASSERT((pTexInfo->Pitch % ElementSize) == 0); |
| UPDATE_BASE_ALIGNMENT(ElementSize); |
| UPDATE_PADDING(pTexInfo->Pitch * 2); // "Surface Padding Requirements --> Render Target and Media Surfaces" |
| } |
| |
| if(pTexInfo->Flags.Gpu.Texture) // (i.e. Sampler Surfaces) /////////////////////////// |
| { |
| UPDATE_BASE_ALIGNMENT(1); // Sampler supports byte alignment (with performance hit if misaligned). |
| |
| if(pGmmGlobalContext->GetWaTable().WaNoMinimizedTrivialSurfacePadding) |
| { |
| if(pTexInfo->Type == RESOURCE_BUFFER) |
| { |
| if(pGmmGlobalContext->GetWaTable().WaNoBufferSamplerPadding) |
| { |
| // Client agreeing to take responsibility for flushing L3 after sampling/etc. |
| } |
| else |
| { |
| // GMM currently receives GENERIC_8BIT for |
| // RESOURCE_BUFFER creations, so we have to assume the |
| // worst-case sample size of 128-bit (unless we alter |
| // our interface meaning): |
| uint32_t ElementSize = 16; |
| |
| // "Surface Padding Requirements --> Sampling Engine Surfaces" |
| UPDATE_PADDING(ElementSize * ((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) == IGFX_GEN8_CORE) ? 512 : 256)); |
| UPDATE_ADDITIONAL_BYTES(16); |
| } |
| } |
| else // RESOURCE_1D/2D... |
| { |
| /* Sampler needs Alignment Unit padding-- |
| but sampler arch confirms that's overly conservative |
| padding--and for trivial (linear, single-subresource) |
| 2D's, even-row (quad-row on BDW.A0) plus additional |
| 64B padding is sufficient. (E.g. pitch overfetch will |
| be caught by subsequent rows or the additional 64B. */ |
| |
| __GMM_ASSERT((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) <= IGFX_GEN8_CORE)); |
| |
| if(GmmIsCompressed(pTexInfo->Format)) |
| { |
| // "For compressed textures...padding at the bottom of the surface is to an even compressed row." |
| UPDATE_PADDING(pTexInfo->Pitch * 2); // (Sampler arch confirmed that even-row is sufficient on BDW despite BDW's 4x4 sampling, since this req is from L2 instead of L1.) |
| } |
| else |
| { |
| UPDATE_PADDING(pTexInfo->Pitch * ((GFX_GET_CURRENT_RENDERCORE(pPlatform->Platform) == IGFX_GEN8_CORE) ? 4 : 2)); // Sampler Fetch Rows: BDW ? 4 : 2 |
| } |
| |
| // "For packed YUV, 96 bpt, 48 bpt, and 24 bpt surface formats, additional padding is required." |
| if(GmmIsYUVPacked(pTexInfo->Format) || (pTexInfo->BitsPerPixel == 96) || (pTexInfo->BitsPerPixel == 48) || (pTexInfo->BitsPerPixel == 24)) |
| { |
| UPDATE_ADDITIONAL_BYTES(16); |
| UPDATE_ADDITIONAL_ROWS(1); |
| } |
| |
| /* "For linear surfaces, additional padding of 64 |
| bytes is required at the bottom of the surface." |
| (Sampler arch confirmed the 64 bytes can overlap with |
| the other "additional 16 bytes" mentions in that section.) */ |
| UPDATE_ADDITIONAL_BYTES(64); |
| } |
| } |
| else |
| { |
| /* For SURFTYPE_BUFFER, SURFTYPE_1D, and |
| SURFTYPE_2D non-array, non-MSAA, non-mip-mapped surfaces in |
| linear memory, the only padding requirement is to the next |
| aligned 64-byte boundary beyond the end of the surface. */ |
| UPDATE_END_ALIGNMENT(64); |
| } |
| } |
| } |
| else // Gpu.NoRestriction... |
| { |
| // Clients specify NoRestriction at their own risk--e.g. it can be |
| // appropriate when using IA-Coherent L3 combined with L3 being in |
| // unified/"Rest" mode (where there won't be write-->read-only |
| // collisions on unintentionally shared cachelines). |
| } |
| |
| { //Finally calculate surf size |
| GMM_GFX_SIZE_T OriginalEnd, RequiredSize; |
| |
| ExistingSysMem.pVirtAddress = |
| (ExistingSysMem.pExistingSysMem & (PAGE_SIZE - 1)) ? |
| ((uint64_t)GFX_ALIGN(ExistingSysMem.pExistingSysMem, |
| BaseAlignment)) : |
| ExistingSysMem.pExistingSysMem; |
| |
| ExistingSysMem.pGfxAlignedVirtAddress = |
| (uint64_t)GFX_ALIGN( |
| (uint64_t)ExistingSysMem.pVirtAddress, PAGE_SIZE); |
| |
| __GMM_ASSERT((ExistingSysMem.pVirtAddress % BaseAlignment) == 0); |
| |
| RequiredSize = pTexInfo->Pitch * Height; |
| |
| RequiredSize = |
| GFX_ALIGN(RequiredSize, SizePadding) + |
| (AdditionalPaddingRows * pTexInfo->Pitch) + |
| AdditionalPaddingBytes; |
| |
| OriginalEnd = ExistingSysMem.pVirtAddress + RequiredSize; |
| RequiredSize += GFX_ALIGN(OriginalEnd, EndAlignment) - OriginalEnd; |
| |
| //Ensure sufficient ExistingSysMem available. |
| if(ExistingSysMem.Size < RequiredSize) |
| { |
| return GMM_ERROR; |
| } |
| |
| Surf.Size = RequiredSize; |
| } |
| |
| GMM_DPF_EXIT; |
| |
| return GMM_SUCCESS; |
| } |