void DecrementBufferMemory(GLenum Type, bool bStructuredBuffer, uint32 NumBytes) { if (bStructuredBuffer) { check(Type == GL_ARRAY_BUFFER); DEC_MEMORY_STAT_BY(STAT_StructuredBufferMemory,NumBytes); } else if (Type == GL_UNIFORM_BUFFER) { DEC_MEMORY_STAT_BY(STAT_UniformBufferMemory,NumBytes); } else if (Type == GL_ELEMENT_ARRAY_BUFFER) { DEC_MEMORY_STAT_BY(STAT_IndexBufferMemory,NumBytes); } else if (Type == GL_PIXEL_UNPACK_BUFFER) { DEC_MEMORY_STAT_BY(STAT_PixelBufferMemory,NumBytes); } else { check(Type == GL_ARRAY_BUFFER); DEC_MEMORY_STAT_BY(STAT_VertexBufferMemory,NumBytes); } }
void UpdateBufferStats(TRefCountPtr<ID3D11Buffer> Buffer, bool bAllocating) { D3D11_BUFFER_DESC Desc; Buffer->GetDesc(&Desc); const bool bUniformBuffer = !!(Desc.BindFlags & D3D11_BIND_CONSTANT_BUFFER); const bool bIndexBuffer = !!(Desc.BindFlags & D3D11_BIND_INDEX_BUFFER); const bool bVertexBuffer = !!(Desc.BindFlags & D3D11_BIND_VERTEX_BUFFER); if (bAllocating) { if (bUniformBuffer) { INC_MEMORY_STAT_BY(STAT_UniformBufferMemory,Desc.ByteWidth); } else if (bIndexBuffer) { INC_MEMORY_STAT_BY(STAT_IndexBufferMemory,Desc.ByteWidth); } else if (bVertexBuffer) { INC_MEMORY_STAT_BY(STAT_VertexBufferMemory,Desc.ByteWidth); } else { INC_MEMORY_STAT_BY(STAT_StructuredBufferMemory,Desc.ByteWidth); } } else { //-V523 if (bUniformBuffer) { DEC_MEMORY_STAT_BY(STAT_UniformBufferMemory,Desc.ByteWidth); } else if (bIndexBuffer) { DEC_MEMORY_STAT_BY(STAT_IndexBufferMemory,Desc.ByteWidth); } else if (bVertexBuffer) { DEC_MEMORY_STAT_BY(STAT_VertexBufferMemory,Desc.ByteWidth); } else { DEC_MEMORY_STAT_BY(STAT_StructuredBufferMemory,Desc.ByteWidth); } } }
void FPrimitiveSceneInfo::RemoveFromScene(bool bUpdateStaticDrawLists) { check(IsInRenderingThread()); // implicit linked list. The destruction will update this "head" pointer to the next item in the list. while(LightList) { FLightPrimitiveInteraction::Destroy(LightList); } // Remove the primitive from the octree. check(OctreeId.IsValidId()); check(Scene->PrimitiveOctree.GetElementById(OctreeId).PrimitiveSceneInfo == this); Scene->PrimitiveOctree.RemoveElement(OctreeId); OctreeId = FOctreeElementId(); IndirectLightingCacheAllocation = NULL; DEC_MEMORY_STAT_BY(STAT_PrimitiveInfoMemory, sizeof(*this) + StaticMeshes.GetAllocatedSize() + Proxy->GetMemoryFootprint()); if (bUpdateStaticDrawLists) { RemoveStaticMeshes(); } }
void FReflectionCaptureFullHDRDerivedData::InitializeFromUncompressedData(const TArray<uint8>& UncompressedData) { DEC_MEMORY_STAT_BY(STAT_ReflectionCaptureMemory, CompressedCapturedData.GetAllocatedSize()); int32 UncompressedSize = UncompressedData.Num() * UncompressedData.GetTypeSize(); TArray<uint8> TempCompressedMemory; // Compressed can be slightly larger than uncompressed TempCompressedMemory.Empty(UncompressedSize * 4 / 3); TempCompressedMemory.AddUninitialized(UncompressedSize * 4 / 3); int32 CompressedSize = TempCompressedMemory.Num() * TempCompressedMemory.GetTypeSize(); verify(FCompression::CompressMemory( (ECompressionFlags)(COMPRESS_ZLIB | COMPRESS_BiasMemory), TempCompressedMemory.GetData(), CompressedSize, UncompressedData.GetData(), UncompressedSize)); // Note: change REFLECTIONCAPTURE_FULL_DERIVEDDATA_VER when modifying the serialization layout FMemoryWriter FinalArchive(CompressedCapturedData, true); FinalArchive << UncompressedSize; FinalArchive << CompressedSize; FinalArchive.Serialize(TempCompressedMemory.GetData(), CompressedSize); INC_MEMORY_STAT_BY(STAT_ReflectionCaptureMemory, CompressedCapturedData.GetAllocatedSize()); }
void UpdateBufferStats(FD3D12ResourceLocation* ResourceLocation, bool bAllocating, uint32 BufferType) { uint64 RequestedSize = ResourceLocation->GetSize(); const bool bUniformBuffer = BufferType == D3D12_BUFFER_TYPE_CONSTANT; const bool bIndexBuffer = BufferType == D3D12_BUFFER_TYPE_INDEX; const bool bVertexBuffer = BufferType == D3D12_BUFFER_TYPE_VERTEX; if (bAllocating) { if (bUniformBuffer) { INC_MEMORY_STAT_BY(STAT_UniformBufferMemory, RequestedSize); } else if (bIndexBuffer) { INC_MEMORY_STAT_BY(STAT_IndexBufferMemory, RequestedSize); } else if (bVertexBuffer) { INC_MEMORY_STAT_BY(STAT_VertexBufferMemory, RequestedSize); } else { INC_MEMORY_STAT_BY(STAT_StructuredBufferMemory, RequestedSize); } } else { if (bUniformBuffer) { DEC_MEMORY_STAT_BY(STAT_UniformBufferMemory, RequestedSize); } else if (bIndexBuffer) { DEC_MEMORY_STAT_BY(STAT_IndexBufferMemory, RequestedSize); } else if (bVertexBuffer) { DEC_MEMORY_STAT_BY(STAT_VertexBufferMemory, RequestedSize); } else { DEC_MEMORY_STAT_BY(STAT_StructuredBufferMemory, RequestedSize); } } }
void FEnvQueryInstance::ReserveItemData(int32 NumAdditionalItems) { DEC_MEMORY_STAT_BY(STAT_AI_EnvQuery_InstanceMemory, RawData.GetAllocatedSize()); RawData.Reserve((RawData.Num() + NumAdditionalItems) * ValueSize); INC_MEMORY_STAT_BY(STAT_AI_EnvQuery_InstanceMemory, RawData.GetAllocatedSize()); }
virtual void InitRHI() { TextureCubeRHI = RHICreateTextureCube(Size, Format, NumMips, 0, NULL); TextureRHI = TextureCubeRHI; if (SourceData) { check(SourceData->Num() > 0); const int32 BlockBytes = GPixelFormats[Format].BlockBytes; int32 MipBaseIndex = 0; for (int32 MipIndex = 0; MipIndex < NumMips; MipIndex++) { const int32 MipSize = 1 << (NumMips - MipIndex - 1); const int32 CubeFaceBytes = MipSize * MipSize * BlockBytes; for (int32 CubeFace = 0; CubeFace < CubeFace_MAX; CubeFace++) { uint32 DestStride = 0; uint8* DestBuffer = (uint8*)RHILockTextureCubeFace(TextureCubeRHI, CubeFace, 0, MipIndex, RLM_WriteOnly, DestStride, false); // Handle DestStride by copying each row for (int32 Y = 0; Y < MipSize; Y++) { uint8* DestPtr = ((uint8*)DestBuffer + Y * DestStride); const int32 SourceIndex = MipBaseIndex + CubeFace * CubeFaceBytes + Y * MipSize * BlockBytes; const uint8* SourcePtr = &(*SourceData)[SourceIndex]; FMemory::Memcpy(DestPtr, SourcePtr, MipSize * BlockBytes); } RHIUnlockTextureCubeFace(TextureCubeRHI, CubeFace, 0, MipIndex, false); } MipBaseIndex += CubeFaceBytes * CubeFace_MAX; } if (!GIsEditor) { // Toss the source data now that we've created the cubemap // Note: can't do this if we ever use this texture resource in the editor and want to save the data later DEC_MEMORY_STAT_BY(STAT_ReflectionCaptureMemory,SourceData->GetAllocatedSize()); SourceData->Empty(); } } // Create the sampler state RHI resource. FSamplerStateInitializerRHI SamplerStateInitializer ( SF_Trilinear, AM_Clamp, AM_Clamp, AM_Clamp ); SamplerStateRHI = RHICreateSamplerState(SamplerStateInitializer); INC_MEMORY_STAT_BY(STAT_ReflectionCaptureTextureMemory,CalcTextureSize(Size,Size,Format,NumMips) * 6); }
void FNavigationOctree::RemoveNode(const FOctreeElementId& Id) { FNavigationOctreeElement& Element = GetElementById(Id); const int32 ElementMemory = Element.GetAllocatedSize(); NodesMemory -= ElementMemory; DEC_MEMORY_STAT_BY(STAT_Navigation_CollisionTreeMemory, ElementMemory); RemoveElement(Id); }
void FNavigationOctree::RemoveNode(const FOctreeElementId* Id) { #if NAVOCTREE_CONTAINS_COLLISION_DATA FNavigationOctreeElement& Data = GetElementById(*Id); const int32 ElementMemory = Data.GetAllocatedSize(); NodesMemory -= ElementMemory; DEC_MEMORY_STAT_BY(STAT_Navigation_CollisionTreeMemory, ElementMemory); #endif RemoveElement(*Id); }
FMemStack::~FMemStack() { check(GIsCriticalError || !NumMarks); Tick(); while( UnusedChunks ) { FTaggedMemory* Old = UnusedChunks; UnusedChunks = UnusedChunks->Next; DEC_MEMORY_STAT_BY( STAT_MemStackAllocated, Old->DataSize + sizeof(FTaggedMemory) ); FMemory::Free( Old ); } }
void FSlateTextureAtlas::Empty() { // Remove all nodes DestroyNodes( RootNode ); RootNode = nullptr; STAT(uint32 MemoryBefore = AtlasData.GetAllocatedSize()); // Clear all raw data AtlasData.Empty(); STAT(uint32 MemoryAfter = AtlasData.GetAllocatedSize()); DEC_MEMORY_STAT_BY(STAT_SlateTextureAtlasMemory, MemoryBefore-MemoryAfter); }
/** Does per-frame global updating for the uniform buffer pool. */ void UniformBufferBeginFrame() { int32 NumCleaned = 0; SCOPE_CYCLE_COUNTER(STAT_D3D11CleanUniformBufferTime); // Clean a limited number of old entries to reduce hitching when leaving a large level for (int32 BucketIndex = 0; BucketIndex < NumPoolBuckets; BucketIndex++) { for (int32 EntryIndex = UniformBufferPool[BucketIndex].Num() - 1; EntryIndex >= 0 && NumCleaned < 10; EntryIndex--) { FPooledUniformBuffer& PoolEntry = UniformBufferPool[BucketIndex][EntryIndex]; check(IsValidRef(PoolEntry.Buffer)); // Clean entries that are unlikely to be reused if (GFrameNumberRenderThread - PoolEntry.FrameFreed > 30) { DEC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers); DEC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, PoolEntry.CreatedSize); NumCleaned++; UpdateBufferStats(PoolEntry.Buffer, false); UniformBufferPool[BucketIndex].RemoveAtSwap(EntryIndex); } } } // Index of the bucket that is now old enough to be reused const int32 SafeFrameIndex = GFrameNumberRenderThread % NumSafeFrames; // Merge the bucket into the free pool array for (int32 BucketIndex = 0; BucketIndex < NumPoolBuckets; BucketIndex++) { int32 LastNum = UniformBufferPool[BucketIndex].Num(); UniformBufferPool[BucketIndex].Append(SafeUniformBufferPools[SafeFrameIndex][BucketIndex]); #if DO_CHECK while (LastNum < UniformBufferPool[BucketIndex].Num()) { check(IsValidRef(UniformBufferPool[BucketIndex][LastNum].Buffer)); LastNum++; } #endif SafeUniformBufferPools[SafeFrameIndex][BucketIndex].Reset(); } }
void UEnvQueryManager::CreateOptionInstance(UEnvQueryOption* OptionTemplate, const TArray<UEnvQueryTest*>& SortedTests, FEnvQueryInstance& Instance) { FEnvQueryOptionInstance OptionInstance; OptionInstance.Generator = OptionTemplate->Generator; OptionInstance.ItemType = OptionTemplate->Generator->ItemType; OptionInstance.Tests.AddZeroed(SortedTests.Num()); for (int32 TestIndex = 0; TestIndex < SortedTests.Num(); TestIndex++) { UEnvQueryTest* TestOb = SortedTests[TestIndex]; OptionInstance.Tests[TestIndex] = TestOb; } DEC_MEMORY_STAT_BY(STAT_AI_EQS_InstanceMemory, Instance.Options.GetAllocatedSize()); const int32 AddedIdx = Instance.Options.Add(OptionInstance); INC_MEMORY_STAT_BY(STAT_AI_EQS_InstanceMemory, Instance.Options.GetAllocatedSize() + Instance.Options[AddedIdx].GetAllocatedSize()); }
void FMemStack::FreeChunks( FTaggedMemory* NewTopChunk ) { while( TopChunk!=NewTopChunk ) { FTaggedMemory* RemoveChunk = TopChunk; TopChunk = TopChunk->Next; RemoveChunk->Next = UnusedChunks; UnusedChunks = RemoveChunk; DEC_MEMORY_STAT_BY( STAT_MemStackUsed, RemoveChunk->DataSize ); } Top = NULL; End = NULL; if( TopChunk ) { Top = TopChunk->Data; End = Top + TopChunk->DataSize; } }
TSharedPtr<FEnvQueryInstance> UEnvQueryManager::PrepareQueryInstance(const FEnvQueryRequest& Request, EEnvQueryRunMode::Type RunMode) { TSharedPtr<FEnvQueryInstance> QueryInstance = CreateQueryInstance(Request.QueryTemplate, RunMode); if (!QueryInstance.IsValid()) { return NULL; } QueryInstance->World = Cast<UWorld>(GetOuter()); QueryInstance->Owner = Request.Owner; DEC_MEMORY_STAT_BY(STAT_AI_EQS_InstanceMemory, QueryInstance->NamedParams.GetAllocatedSize()); // @TODO: interface for providing default named params (like custom ranges in AI) QueryInstance->NamedParams = Request.NamedParams; INC_MEMORY_STAT_BY(STAT_AI_EQS_InstanceMemory, QueryInstance->NamedParams.GetAllocatedSize()); QueryInstance->QueryID = NextQueryID++; return QueryInstance; }
bool FEnvQueryInstance::PrepareContext(UClass* ContextClass, FEnvQueryContextData& ContextData) { if (ContextClass == NULL) { return false; } if (ContextClass != UEnvQueryContext_Item::StaticClass()) { FEnvQueryContextData* CachedData = ContextCache.Find(ContextClass); if (CachedData == NULL) { UEnvQueryContext* ContextOb = ContextClass->GetDefaultObject<UEnvQueryContext>(); ContextOb->ProvideDelegate.ExecuteIfBound(*this, ContextData); DEC_MEMORY_STAT_BY(STAT_AI_EnvQuery_InstanceMemory, GetContextAllocatedSize()); ContextCache.Add(ContextClass, ContextData); INC_MEMORY_STAT_BY(STAT_AI_EnvQuery_InstanceMemory, GetContextAllocatedSize()); } else { ContextData = *CachedData; } } if (ContextData.NumValues == 0) { UE_LOG(LogEQS, Warning, TEXT("Query [%s] is missing values for context [%s], skipping test %d:%d [%s]"), *QueryName, *UEnvQueryTypes::GetShortTypeName(ContextClass), OptionIndex, CurrentTest, *UEnvQueryTypes::GetShortTypeName(Options[OptionIndex].TestDelegates[CurrentTest].GetUObject())); return false; } return true; }
FNavigationOctree::~FNavigationOctree() { DEC_DWORD_STAT_BY( STAT_NavigationMemory, sizeof(*this) ); DEC_MEMORY_STAT_BY(STAT_Navigation_CollisionTreeMemory, NodesMemory); }
FUniformBufferRHIRef FD3D11DynamicRHI::RHICreateUniformBuffer(const void* Contents,const FRHIUniformBufferLayout& Layout,EUniformBufferUsage Usage) { check(IsInRenderingThread()); FD3D11UniformBuffer* NewUniformBuffer = nullptr; const uint32 NumBytes = Layout.ConstantBufferSize; if (NumBytes > 0) { // Constant buffers must also be 16-byte aligned. check(Align(NumBytes,16) == NumBytes); check(Align(Contents,16) == Contents); check(NumBytes <= D3D11_REQ_CONSTANT_BUFFER_ELEMENT_COUNT * 16); check(NumBytes < (1 << NumPoolBuckets)); SCOPE_CYCLE_COUNTER(STAT_D3D11UpdateUniformBufferTime); if (IsPoolingEnabled()) { TRefCountPtr<ID3D11Buffer> UniformBufferResource; FRingAllocation RingAllocation; if (!RingAllocation.IsValid()) { // Find the appropriate bucket based on size const uint32 BucketIndex = GetPoolBucketIndex(NumBytes); TArray<FPooledUniformBuffer>& PoolBucket = UniformBufferPool[BucketIndex]; if (PoolBucket.Num() > 0) { // Reuse the last entry in this size bucket FPooledUniformBuffer FreeBufferEntry = PoolBucket.Pop(); check(IsValidRef(FreeBufferEntry.Buffer)); UniformBufferResource = FreeBufferEntry.Buffer; checkf(FreeBufferEntry.CreatedSize >= NumBytes, TEXT("%u %u %u %u"), NumBytes, BucketIndex, FreeBufferEntry.CreatedSize, GetPoolBucketSize(NumBytes)); DEC_DWORD_STAT(STAT_D3D11NumFreeUniformBuffers); DEC_MEMORY_STAT_BY(STAT_D3D11FreeUniformBufferMemory, FreeBufferEntry.CreatedSize); } // Nothing usable was found in the free pool, create a new uniform buffer if (!IsValidRef(UniformBufferResource)) { D3D11_BUFFER_DESC Desc; // Allocate based on the bucket size, since this uniform buffer will be reused later Desc.ByteWidth = GetPoolBucketSize(NumBytes); // Use D3D11_USAGE_DYNAMIC, which allows multiple CPU writes for pool reuses // This is method of updating is vastly superior to creating a new constant buffer each time with D3D11_USAGE_IMMUTABLE, // Since that inserts the data into the command buffer which causes GPU flushes Desc.Usage = D3D11_USAGE_DYNAMIC; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; Desc.MiscFlags = 0; Desc.StructureByteStride = 0; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc, NULL, UniformBufferResource.GetInitReference())); UpdateBufferStats(UniformBufferResource, true); } check(IsValidRef(UniformBufferResource)); D3D11_MAPPED_SUBRESOURCE MappedSubresource; // Discard previous results since we always do a full update VERIFYD3D11RESULT(Direct3DDeviceIMContext->Map(UniformBufferResource, 0, D3D11_MAP_WRITE_DISCARD, 0, &MappedSubresource)); check(MappedSubresource.RowPitch >= NumBytes); FMemory::Memcpy(MappedSubresource.pData, Contents, NumBytes); Direct3DDeviceIMContext->Unmap(UniformBufferResource, 0); } NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, RingAllocation); } else { // No pooling D3D11_BUFFER_DESC Desc; Desc.ByteWidth = NumBytes; Desc.Usage = D3D11_USAGE_IMMUTABLE; Desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; Desc.CPUAccessFlags = 0; Desc.MiscFlags = 0; Desc.StructureByteStride = 0; D3D11_SUBRESOURCE_DATA ImmutableData; ImmutableData.pSysMem = Contents; ImmutableData.SysMemPitch = ImmutableData.SysMemSlicePitch = 0; TRefCountPtr<ID3D11Buffer> UniformBufferResource; VERIFYD3D11RESULT(Direct3DDevice->CreateBuffer(&Desc,&ImmutableData,UniformBufferResource.GetInitReference())); NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, UniformBufferResource, FRingAllocation()); } } else { // This uniform buffer contains no constants, only a resource table. NewUniformBuffer = new FD3D11UniformBuffer(this, Layout, nullptr, FRingAllocation()); } if (Layout.Resources.Num()) { int32 NumResources = Layout.Resources.Num(); FRHIResource** InResources = (FRHIResource**)((uint8*)Contents + Layout.ResourceOffset); NewUniformBuffer->ResourceTable.Empty(NumResources); NewUniformBuffer->ResourceTable.AddZeroed(NumResources); for (int32 i = 0; i < NumResources; ++i) { check(InResources[i]); NewUniformBuffer->ResourceTable[i] = InResources[i]; } NewUniformBuffer->RawResourceTable.Empty(NumResources); NewUniformBuffer->RawResourceTable.AddZeroed(NumResources); } return NewUniformBuffer; }
virtual void ReleaseRHI() { DEC_MEMORY_STAT_BY(STAT_ReflectionCaptureTextureMemory,CalcTextureSize(Size,Size,Format,NumMips) * 6); TextureCubeRHI.SafeRelease(); FTexture::ReleaseRHI(); }
FReflectionCaptureFullHDRDerivedData::~FReflectionCaptureFullHDRDerivedData() { DEC_MEMORY_STAT_BY(STAT_ReflectionCaptureMemory, CompressedCapturedData.GetAllocatedSize()); }
FReflectionCaptureEncodedHDRDerivedData::~FReflectionCaptureEncodedHDRDerivedData() { DEC_MEMORY_STAT_BY(STAT_ReflectionCaptureMemory,CapturedData.GetAllocatedSize()); }