PoolSize

PoolSize

#Overview

name: PoolSize

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 67 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of PoolSize is to define the size of a memory pool for resource allocation in various subsystems of Unreal Engine 5. It is commonly used to set the size of texture pools, buffer pools, and other resource pools in the rendering and memory management systems.

Based on the provided code snippets, PoolSize is utilized in several Unreal Engine subsystems, plugins, and modules:

  1. Rendering system (D3D11, D3D12, Vulkan, OpenGL)
  2. Texture streaming system
  3. Buffer allocation system
  4. Landscape editing system
  5. Movie Pipeline rendering system
  6. PCG (Procedural Content Generation) system
  7. Replication Graph system

The value of PoolSize is typically set in one of the following ways:

  1. Calculated as a percentage of total available VRAM (GPoolSizeVRAMPercentage)
  2. Set through configuration files or command-line arguments
  3. Defined as a constant value for specific subsystems
  4. Determined dynamically based on system capabilities or requirements

PoolSize often interacts with other variables such as:

  1. GTexturePoolSize: The total size of the texture pool
  2. MaxAllocationSize: The maximum size of a single allocation from the pool
  3. TotalGraphicsMemory: The total available graphics memory
  4. MemoryBudget: The memory budget for streaming assets

Developers should be aware of the following when using PoolSize:

  1. Setting an appropriate PoolSize is crucial for optimal performance and memory usage
  2. Too small a PoolSize may lead to frequent allocations and deallocations, impacting performance
  3. Too large a PoolSize may waste memory, especially on systems with limited resources
  4. Different subsystems may have different optimal PoolSize values

Best practices when using PoolSize include:

  1. Adjusting PoolSize based on the target hardware and specific application requirements
  2. Monitoring memory usage and performance to fine-tune PoolSize
  3. Using dynamic allocation strategies when possible to adapt to different hardware configurations
  4. Considering the trade-offs between memory usage and performance when setting PoolSize
  5. Documenting the rationale behind chosen PoolSize values for different subsystems

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:1811, section: [TextureStreaming]

#References in C++ code

#Callsites

This variable is referenced in the following C++ source code:

#Loc: <Workspace>/Engine/Plugins/MovieScene/MovieRenderPipeline/Source/MovieRenderPipelineRenderPasses/Private/MoviePipelineDeferredPasses.cpp:249

Scope (from outer to inner):

file
function     void UMoviePipelineDeferredPassBase::SetupImpl

Source code excerpt:

	// the accumulators can be tied up for multiple game frames, thus we must have at least one per output and we can only reuse them between
	// actual output frames (not engine frames). This doesn't allocate memory until they're actually used so it's ok to over-allocate.
	int32 PoolSize = (TotalNumberOfAccumulators + (ActivePostProcessMaterials.Num()*NumCameras) + 1) * 3;
	AccumulatorPool = MakeShared<TAccumulatorPool<FImageOverlappedAccumulator>, ESPMode::ThreadSafe>(PoolSize);
	
	PreviousCustomDepthValue.Reset();
	PreviousDumpFramesValue.Reset();
	PreviousColorFormatValue.Reset();

	// This scene view extension will be released automatically as soon as Render Sequence is torn down.

#Loc: <Workspace>/Engine/Plugins/PCG/Source/PCG/Private/RuntimeGen/PCGRuntimeGenScheduler.cpp:96

Scope (from outer to inner):

file
function     void FPCGRuntimeGenScheduler::Tick

Source code excerpt:

	}

	// Initialize RuntimeGen PA pool if necessary. If PoolSize is 0, then we have not initialized the pool yet.
	if (!GenSources.IsEmpty() || !GeneratedComponents.IsEmpty())
	{
		if (PartitionActorPoolSize == 0 && PCGRuntimeGenSchedulerHelpers::CVarRuntimeGenerationEnablePooling.GetValueOnAnyThread())
		{
			AddPartitionActorPoolCount(PCGRuntimeGenSchedulerHelpers::CVarRuntimeGenerationBasePoolSize.GetValueOnAnyThread());
		}

#Loc: <Workspace>/Engine/Plugins/PCG/Source/PCG/Private/RuntimeGen/PCGRuntimeGenScheduler.cpp:691

Scope (from outer to inner):

file
function     void FPCGRuntimeGenScheduler::TickCVars

Source code excerpt:

	bPoolingWasEnabledLastFrame = bPoolingEnabled;

	// Handle when the base PA PoolSize is modified. Cleanup all local components and reset the pool with the correct number of PAs.
	if (PCGRuntimeGenSchedulerHelpers::CVarRuntimeGenerationEnablePooling.GetValueOnAnyThread())
	{
		// Don't allow a pool size <= 0
		const uint32 BasePoolSize = FMath::Max(1, PCGRuntimeGenSchedulerHelpers::CVarRuntimeGenerationBasePoolSize.GetValueOnAnyThread());

		if (BasePoolSizeLastFrame != BasePoolSize)

#Loc: <Workspace>/Engine/Plugins/Runtime/ReplicationGraph/Source/Private/ReplicationGraphTypes.cpp:49

Scope: file

Source code excerpt:

	void LogStats(int32 Mode, FOutputDevice& Ar=*GLog);
	/** Logs details about a specific list */
	void LogDetails(int32 PoolSize, int32 BlockIdx, int32 ListIdx, FOutputDevice& Ar=*GLog);

	void CountBytes(FArchive& Ar) const
	{
		PoolTable.CountBytes(Ar);
		for (const FPool& Pool : PoolTable)
		{

#Loc: <Workspace>/Engine/Plugins/Runtime/ReplicationGraph/Source/Private/ReplicationGraphTypes.cpp:264

Scope (from outer to inner):

file
function     void PrintRepListDetails

Source code excerpt:

	GActorListAllocator.LogStats(mode, Ar);
}
void PrintRepListDetails(int32 PoolSize, int32 BlockIdx, int32 ListIdx)
{
	GActorListAllocator.LogDetails(PoolSize, BlockIdx, ListIdx);
}
#endif

void PreAllocateRepList(int32 ListSize, int32 NumLists)
{
	// nothing

#Loc: <Workspace>/Engine/Plugins/Runtime/ReplicationGraph/Source/Private/ReplicationGraphTypes.cpp:395

Scope (from outer to inner):

file
function     void TActorListAllocator<NumListsPerBlock, MaxNumPools>::LogDetails

Source code excerpt:


template<uint32 NumListsPerBlock, uint32 MaxNumPools>
void TActorListAllocator<NumListsPerBlock, MaxNumPools>::LogDetails(int32 PoolSize, int32 BlockIdx, int32 ListIdx, FOutputDevice& Ar)
{
	FPool* Pool = PoolTable.FindByPredicate([&PoolSize](const FPool& InPool) { return PoolSize <= InPool.ListSize; });
	if (!Pool)
	{
		Ar.Logf(TEXT("Could not find suitable PoolSize %d"), PoolSize);
		return;
	}

	if (ListIdx > NumListsPerBlock)
	{
		Ar.Logf(TEXT("ListIdx %d too big. Should be <= %d."), ListIdx, NumListsPerBlock);

#Loc: <Workspace>/Engine/Plugins/Runtime/ReplicationGraph/Source/Public/ReplicationGraphTypes.h:511

Scope: file

Source code excerpt:

#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
	// Intended to be called from immediate mode window while debugging
	extern "C" DLLEXPORT void PrintRepListDetails(int32 PoolSize, int32 BlockIdx, int32 ListIdx);
	extern "C" DLLEXPORT void PrintRepListStats(int32 mode=0);
	
	void PrintRepListStatsAr(int32 mode, FOutputDevice& Ar=*GLog);	
#endif

#Loc: <Workspace>/Engine/Source/Developer/Zen/Internal/ZenClient.h:58

Scope (from outer to inner):

file
namespace    UE::Zen
class        class IZenClientPool

Source code excerpt:

	virtual ~IZenClientPool() = default;

	virtual bool Connect(FStringView Host, int32 Port, int32 PoolSize = 8) = 0;
	virtual void Disconnect() = 0;
	virtual bool IsConnected() const = 0;

	virtual bool SendRequest(FCbPackage&& Request, FOnStreamResponse&& OnResponse) = 0;
	virtual bool SendRequest(FCbObject&& Request, FOnStreamResponse&& OnResponse) = 0;
	virtual bool SendStreamRequest(FCbObject&& Request, FOnStreamResponse&& OnStreamResponse) = 0;

#Loc: <Workspace>/Engine/Source/Developer/Zen/Private/ZenClient.cpp:683

Scope (from outer to inner):

file
namespace    UE::Zen
class        class FZenClientPool final : public IZenClientPool

Source code excerpt:

	virtual ~FZenClientPool();

	virtual bool Connect(FStringView Host, int32 Port, int32 PoolSize = 8) override;
	virtual void Disconnect() override;

	virtual inline bool IsConnected() const override { return bConnected; }

	virtual bool SendRequest(FCbPackage&& Request, FOnStreamResponse&& OnResponse) override;
	virtual bool SendRequest(FCbObject&& Request, FOnStreamResponse&& OnResponse) override;

#Loc: <Workspace>/Engine/Source/Developer/Zen/Private/ZenClient.cpp:732

Scope (from outer to inner):

file
namespace    UE::Zen
function     bool FZenClientPool::Connect

Source code excerpt:

}

bool FZenClientPool::Connect(FStringView Host, int32 Port, int32 PoolSize)
{
	check(bConnected == false);

	Pool.SetNum(PoolSize);

	for (FPoolEntry& Entry : Pool)
	{
		if (Entry.Client.Connect(Host, Port) == false)
		{
			return false;		

#Loc: <Workspace>/Engine/Source/Developer/Zen/Private/ZenClient.cpp:756

Scope (from outer to inner):

file
namespace    UE::Zen
function     bool FZenClientPool::Connect

Source code excerpt:

	PoolHead = PoolTail = &Pool[0];

	for (int32 Index = 1; Index < PoolSize; ++Index)
	{
		Pool[Index].Next = PoolTail;
		PoolTail = &Pool[Index];
	}

#endif

#Loc: <Workspace>/Engine/Source/Developer/Zen/Private/ZenClient.cpp:825

Scope (from outer to inner):

file
namespace    UE::Zen
function     FZenClientPool::FPoolEntry* FZenClientPool::GetClient

Source code excerpt:

#if UE_WITH_ZEN_NON_BLOCKING_POOL

	const int32 PoolSize = Pool.Num();
	int32 EntryIndex = PoolEntryStartIndex.IncrementExchange() % PoolSize;
	int32 SpinCount = 0;
	
	for (;;)
	{
		FPoolEntry& Entry = Pool[EntryIndex];
			

#Loc: <Workspace>/Engine/Source/Developer/Zen/Private/ZenClient.cpp:842

Scope (from outer to inner):

file
namespace    UE::Zen
function     FZenClientPool::FPoolEntry* FZenClientPool::GetClient

Source code excerpt:

		}

		EntryIndex = (EntryIndex + 1) % PoolSize;
		
		if (++SpinCount >= PoolSize * 2)
		{
			SpinCount = 0;
			FPlatformProcess::Sleep(0.01f);
		}
	}
#else

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestObjectPool.cpp:19

Scope (from outer to inner):

file
namespace    ChaosTest
function     GTEST_TEST

Source code excerpt:

		FPool::FPtr Ptr = Pool.Alloc(3);

		const int32 PoolSize = Pool.GetAllocatedSize();

		for(int32 i = 0; i < 32; ++i)
		{
			Pool.Free(Ptr);
			Ptr = Pool.Alloc(4);
		}

		// Make sure the freelist is working - should only ever have 3 elements allocated
		EXPECT_EQ(PoolSize, Pool.GetAllocatedSize());
		EXPECT_EQ(Pool.GetNumAllocatedBlocks(), 1);
	}

	GTEST_TEST(ObjectPoolTests, TestPool_CompoundType)
	{
		// Tests Alloc/Free works with class types

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestObjectPool.cpp:55

Scope (from outer to inner):

file
namespace    ChaosTest
function     GTEST_TEST

Source code excerpt:

		FPool::FPtr Ptr = Pool.Alloc(3, 3.0f);

		const int32 PoolSize = Pool.GetAllocatedSize();

		for(int32 i = 0; i < 32; ++i)
		{
			Pool.Free(Ptr);
			Ptr = Pool.Alloc(4, 4.0f);
		}

		// Make sure the freelist is working - should only ever have 3 elements allocated
		EXPECT_EQ(PoolSize, Pool.GetAllocatedSize());
		EXPECT_EQ(Pool.GetNumAllocatedBlocks(), 1);
	}

	GTEST_TEST(ObjectPoolTests, TestPool_ComplexType)
	{
		// Tests Alloc/Free works with non-trivial types

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestObjectPool.cpp:101

Scope (from outer to inner):

file
namespace    ChaosTest
function     GTEST_TEST

Source code excerpt:

		FPool::FPtr Ptr = Pool.Alloc(ConstructorCount, DestructorCount);

		const int32 PoolSize = Pool.GetAllocatedSize();

		for(int32 i = 0; i < 32; ++i)
		{
			Pool.Free(Ptr);
			Ptr = Pool.Alloc(ConstructorCount, DestructorCount);
		}

		// Make sure the freelist is working - should only ever have 3 elements allocated
		EXPECT_EQ(PoolSize, Pool.GetAllocatedSize());
		EXPECT_EQ(Pool.GetNumAllocatedBlocks(), 1);

		// Make sure when types require destructors they area actually called
		EXPECT_EQ(ConstructorCount, 35);
		EXPECT_EQ(DestructorCount, 32);
	}

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestObjectPool.cpp:132

Scope (from outer to inner):

file
namespace    ChaosTest
function     GTEST_TEST

Source code excerpt:

		}

		const int32 PoolSize = Pool.GetAllocatedSize();

		Pool.Reset();

		for(int32 i = 0; i < 32; ++i)
		{
			Pool.Alloc(i);

#Loc: <Workspace>/Engine/Source/Programs/HeadlessChaos/Private/HeadlessChaosTestObjectPool.cpp:142

Scope (from outer to inner):

file
namespace    ChaosTest
function     GTEST_TEST

Source code excerpt:


		// Make sure reset works, the allocated size should never change as we only need one block
		EXPECT_EQ(PoolSize, Pool.GetAllocatedSize());
		EXPECT_EQ(Pool.GetNumAllocatedBlocks(), 1);
	}

	GTEST_TEST(ObjectPoolTests, TestPool_ComplexType_Reset)
	{
		// Tests calling Reset on the pool with items that require destruction actually destructs the items

#Loc: <Workspace>/Engine/Source/Runtime/Apple/MetalRHI/Private/MetalRHI.cpp:530

Scope: file

Source code excerpt:

	if ( GPoolSizeVRAMPercentage > 0 && MemoryStats.TotalGraphicsMemory > 0 )
	{
		float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(MemoryStats.TotalGraphicsMemory);
		
		// Truncate GTexturePoolSize to MB (but still counted in bytes)
		GTexturePoolSize = int64(FGenericPlatformMath::TruncToFloat(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;
		
		UE_LOG(LogRHI,Log,TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
			   GTexturePoolSize / 1024 / 1024,
			   GPoolSizeVRAMPercentage,
			   MemoryStats.TotalGraphicsMemory / 1024 / 1024);
	}

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/AutoRTFM/ObjectPool.h:7

Scope (from outer to inner):

file
namespace    AutoRTFM

Source code excerpt:

{

template<typename T, size_t PoolSize>
class TObjectPool
{
public:
    TObjectPool() = default;

    T* Allocate()

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/AutoRTFM/ObjectPool.h:22

Scope (from outer to inner):

file
namespace    AutoRTFM
class        class TObjectPool
function     T* Allocate

Source code excerpt:

        }

        ASSERT(HighWatermark < PoolSize);
        return Lines + HighWatermark++;
    }

    void Deallocate(T* Line)
    {
        FFreeNode* FreeNode = reinterpret_cast<FFreeNode*>(Line);

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/AutoRTFM/ObjectPool.h:39

Scope (from outer to inner):

file
namespace    AutoRTFM
class        class TObjectPool

Source code excerpt:

    };
    
    T Lines[PoolSize];
    size_t HighWatermark{0};
    FFreeNode* NextFree{nullptr};
};

} // namespace AutoRTFM

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/HAL/MallocBinned.cpp:603

Scope (from outer to inner):

file
function     static FPoolInfo* AllocatePoolMemory

Source code excerpt:

	}

	static FPoolInfo* AllocatePoolMemory(FMallocBinned& Allocator, FPoolTable* Table, uint32 PoolSize, uint16 TableIndex)
	{
		const uint32 PageSize = Allocator.PageSize;

		// Must create a new pool.
		uint32 Blocks   = PoolSize / Table->BlockSize;
		uint32 Bytes    = Blocks * Table->BlockSize;
		UPTRINT OsBytes = Align(Bytes, PageSize);

		checkSlow(Blocks >= 1);
		checkSlow(PoolSize >= Bytes);
		
		FFreeMem* Free = nullptr;
		SIZE_T ActualPoolSize; //TODO: use this to reduce waste?
		
#if USE_OS_SMALL_BLOCK_GRAB_MEMORY_FROM_OS
		Free = GetAllocFromSmallBlockGrab(Allocator, OsBytes);

#Loc: <Workspace>/Engine/Source/Runtime/Core/Private/Misc/ConfigCacheIni.cpp:1368

Scope (from outer to inner):

file
function     void FConfigFile::OverrideFromCommandline

Source code excerpt:

	//		-ini:IniName:[Section1]:Key1=Value1,[Section2]:Key2=Value2
	// for example:
	//		-ini:Engine:[/Script/Engine.Engine]:bSmoothFrameRate=False,[TextureStreaming]:PoolSize=100
	//			(will update the cache after the final combined engine.ini)
	const TCHAR* CommandlineStream = FCommandLine::Get();
	while(FParse::Value(CommandlineStream, *FString::Printf(TEXT("%s%s"), CommandlineOverrideSpecifiers::IniSwitchIdentifier, *FPaths::GetBaseFilename(Filename)), Settings, false))
	{
		// break apart on the commas
		TArray<FString> SettingPairs;

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1429

Scope (from outer to inner):

file
function     FD3D12BufferPool* FD3D12DefaultBufferAllocator::CreateBufferPool

Source code excerpt:

	const FString Name(L"D3D12 Pool Allocator");
	EResourceAllocationStrategy AllocationStrategy = FD3D12PoolAllocator::GetResourceAllocationStrategy(InResourceFlags, InResourceStateMode, Alignment);
	uint64 PoolSize = InHeapType == D3D12_HEAP_TYPE_READBACK ? READBACK_BUFFER_POOL_DEFAULT_POOL_SIZE : BUFFER_POOL_DEFAULT_POOL_SIZE;
	uint64 PoolAlignment = (AllocationStrategy == EResourceAllocationStrategy::kPlacedResource) ? MIN_PLACED_RESOURCE_SIZE : kD3D12ManualSubAllocationAlignment;
	uint64 MaxAllocationSize = InHeapType == D3D12_HEAP_TYPE_READBACK ? READBACK_BUFFER_POOL_MAX_ALLOC_SIZE : BUFFER_POOL_DEFAULT_POOL_MAX_ALLOC_SIZE;
	FRHIMemoryPool::EFreeListOrder FreeListOrder = FRHIMemoryPool::EFreeListOrder::SortBySize;

	// Disable defrag if not Default memory
	bool bDefragEnabled = (InitConfig.HeapType == D3D12_HEAP_TYPE_DEFAULT);

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1446

Scope (from outer to inner):

file
function     FD3D12BufferPool* FD3D12DefaultBufferAllocator::CreateBufferPool

Source code excerpt:


		// Use custom pool and allocation size for RT structures because they don't defrag and will thus 'waste' more memory
		PoolSize = BUFFER_POOL_RT_ACCELERATION_STRUCTURE_POOL_SIZE;
		MaxAllocationSize = BUFFER_POOL_RT_ACCELERATION_STRUCTURE_MAX_ALLOC_SIZE;
	}
#endif // D3D12_RHI_RAYTRACING

	FD3D12BufferPool* NewPool = new FD3D12PoolAllocator(Device, GetVisibilityMask(), InitConfig, Name, AllocationStrategy, PoolSize, PoolAlignment, MaxAllocationSize, FreeListOrder, bDefragEnabled, TraceHeapId);

#else // USE_BUFFER_POOL_ALLOCATOR

	EResourceAllocationStrategy AllocationStrategy = FD3D12DefaultBufferPool::GetResourceAllocationStrategy(InResourceFlags, InResourceStateMode, Alignment);

	// if placed then 64KB alignment required :(

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1725

Scope (from outer to inner):

file
function     FD3D12TextureAllocatorPool::FD3D12TextureAllocatorPool

Source code excerpt:


		const FString Name(L"D3D12 ReadOnly4K Texture Pool Allocator");
		uint64 PoolSize = 4 * 1024 * 1024;
		uint64 MaxAllocationSize = PoolSize;
		bool bDefragEnabled = false; // Disable defrag on 4K pool because it shouldn't really fragment - all allocations are 4K or multiple of 4K and pretty small
		FD3D12PoolAllocator* ReadOnly4KPool = new FD3D12PoolAllocator(Device, GetVisibilityMask(), InitConfig, Name, AllocationStrategy, PoolSize, D3D12_SMALL_RESOURCE_PLACEMENT_ALIGNMENT, MaxAllocationSize, FreeListOrder, bDefragEnabled, TraceHeapId);
		ReadOnly4KPool->Initialize();

		PoolAllocators[(int)EPoolType::ReadOnly4K] = ReadOnly4KPool;
	}

	{

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1739

Scope (from outer to inner):

file
function     FD3D12TextureAllocatorPool::FD3D12TextureAllocatorPool

Source code excerpt:


		const FString Name(L"D3D12 ReadOnly Texture Pool Allocator");
		uint64 PoolSize = GD3D12PoolAllocatorReadOnlyTextureVRAMPoolSize;
		uint64 MaxAllocationSize = GD3D12PoolAllocatorReadOnlyTextureVRAMMaxAllocationSize;
		bool bDefragEnabled = true;
		FD3D12PoolAllocator* ReadOnlyPool = new FD3D12PoolAllocator(Device, GetVisibilityMask(), InitConfig, Name, AllocationStrategy, PoolSize, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, MaxAllocationSize, FreeListOrder, bDefragEnabled, TraceHeapId);
		ReadOnlyPool->Initialize();

		PoolAllocators[(int)EPoolType::ReadOnly] = ReadOnlyPool;
	}

	{

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1753

Scope (from outer to inner):

file
function     FD3D12TextureAllocatorPool::FD3D12TextureAllocatorPool

Source code excerpt:


		const FString Name(L"D3D12 RT Texture Pool Allocator");
		uint64 PoolSize = GD3D12PoolAllocatorRTUAVTextureVRAMPoolSize;
		uint64 MaxAllocationSize = GD3D12PoolAllocatorRTUAVTextureVRAMMaxAllocationSize;
		// FD3D12ResourceLocation::OnAllocationMoved doesn't correctly retrieve the clear value when recreating moved resources, so we need to disable defrag for this pool for the time being.
		bool bDefragEnabled = false;
		FD3D12PoolAllocator* RTPool = new FD3D12PoolAllocator(Device, GetVisibilityMask(), InitConfig, Name, AllocationStrategy, PoolSize, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, MaxAllocationSize, FreeListOrder, bDefragEnabled, TraceHeapId);
		RTPool->Initialize();

		PoolAllocators[(int)EPoolType::RenderTarget] = RTPool;
	}

	{

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Allocation.cpp:1768

Scope (from outer to inner):

file
function     FD3D12TextureAllocatorPool::FD3D12TextureAllocatorPool

Source code excerpt:


		const FString Name(L"D3D12 UAV Texture Pool Allocator");
		uint64 PoolSize = GD3D12PoolAllocatorRTUAVTextureVRAMPoolSize;
		uint64 MaxAllocationSize = GD3D12PoolAllocatorRTUAVTextureVRAMMaxAllocationSize;
		// Defrag doesn't correctly handle resources which need the BCn/UINT UAV aliasing workaround, so we'll turn off defrag for this heap for now.
		bool bDefragEnabled = false;
		FD3D12PoolAllocator* UAVPool = new FD3D12PoolAllocator(Device, GetVisibilityMask(), InitConfig, Name, AllocationStrategy, PoolSize, D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, MaxAllocationSize, FreeListOrder, bDefragEnabled, TraceHeapId);
		UAVPool->Initialize();

		PoolAllocators[(int)EPoolType::UAV] = UAVPool;
	}
}

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12PoolAllocator.cpp:49

Scope (from outer to inner):

file
function     void FD3D12MemoryPool::Init

Source code excerpt:

void FD3D12MemoryPool::Init()
{
	if (PoolSize == 0)
	{
		return;
	}

	FD3D12Device* Device = GetParentDevice();
	FD3D12Adapter* Adapter = Device->GetParentAdapter();

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12PoolAllocator.cpp:67

Scope (from outer to inner):

file
function     void FD3D12MemoryPool::Init

Source code excerpt:


		D3D12_HEAP_DESC Desc = {};
		Desc.SizeInBytes = PoolSize;
		Desc.Properties = HeapProps;
		Desc.Alignment = 0;
		Desc.Flags = InitConfig.HeapFlags;

		// All all resources types on heap when tracking allocations (need to be able to create a buffer on it to extract the base gpu address)
		// (Tier 2 support already checked when this flag is enabled)

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12PoolAllocator.cpp:107

Scope (from outer to inner):

file
function     void FD3D12MemoryPool::Init

Source code excerpt:

			LLM_SCOPED_PAUSE_TRACKING_FOR_TRACKER(ELLMTracker::Default, ELLMAllocType::System);
			const D3D12_HEAP_PROPERTIES HeapProps = CD3DX12_HEAP_PROPERTIES(InitConfig.HeapType, GetGPUMask().GetNative(), GetVisibilityMask().GetNative());
			VERIFYD3D12RESULT(Adapter->CreateBuffer(HeapProps, GetGPUMask(), InitConfig.InitialResourceState, ED3D12ResourceStateMode::SingleState, InitConfig.InitialResourceState, PoolSize, BackingResource.GetInitReference(), TEXT("Resource Allocator Underlying Buffer"), InitConfig.ResourceFlags));
#if UE_MEMORY_TRACE_ENABLED
			MemoryTrace_MarkAllocAsHeap(BackingResource->GetGPUVirtualAddress(), TraceHeapId);
#endif
		}

		if (IsCPUAccessible(InitConfig.HeapType))

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12PoolAllocator.cpp:135

Scope (from outer to inner):

file
function     void FD3D12MemoryPool::Init

Source code excerpt:

#endif // D3D12_RHI_RAYTRACING

	LLM_SCOPED_PAUSE_TRACKING_WITH_ENUM_AND_AMOUNT_BYTAG(D3D12AllocatorUnused, int64(PoolSize), ELLMTracker::Platform, ELLMAllocType::System);
	FRHIMemoryPool::Init();
}


void FD3D12MemoryPool::Destroy()
{

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12PoolAllocator.cpp:560

Scope (from outer to inner):

file
function     FRHIMemoryPool* FD3D12PoolAllocator::CreateNewPool

Source code excerpt:

	// Find out the pool size - use default, but if allocation doesn't fit then round up to next power of 2
	// so it 'always' fits the pool allocator
	uint32 PoolSize = DefaultPoolSize;
	if (InMinimumAllocationSize > PoolSize)
	{
		check(InMinimumAllocationSize <= MaxAllocationSize);
		PoolSize = FMath::Min(FMath::RoundUpToPowerOfTwo(InMinimumAllocationSize), (uint32)MaxAllocationSize);
	}

	FD3D12MemoryPool* NewPool = new FD3D12MemoryPool(GetParentDevice(),	GetVisibilityMask(), InitConfig,
		Name, AllocationStrategy, InPoolIndex, PoolSize, PoolAlignment, InAllocationResourceType, FreeListOrder, TraceHeapId);
	NewPool->Init();
	return NewPool;
}


bool FD3D12PoolAllocator::HandleDefragRequest(FRHICommandListBase& RHICmdList, FRHIPoolAllocationData* InSourceBlock, FRHIPoolAllocationData& InTmpTargetBlock)

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/D3D12Texture.cpp:679

Scope (from outer to inner):

file
function     void FD3D12DynamicRHI::RHIGetTextureMemoryStats

Source code excerpt:

			{
				// The texture pool size is a percentage of GTotalGraphicsMemory.
				const float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(OutStats.TotalGraphicsMemory);

				// Truncate texture pool size to MB (but still counted in bytes).
				DesiredTexturePoolSize = int64(FGenericPlatformMath::TruncToFloat(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;
			}

			// Make sure the desired texture pool size doesn't make us go overbudget.
			const bool bIsLimitedTexturePoolSize = GTexturePoolSize > 0;
			const int64 LimitedMaxTexturePoolSize = bIsLimitedTexturePoolSize ? GTexturePoolSize : INT64_MAX;
			const int64 MaxTexturePoolSize = FMath::Min(PreviousTexturePoolSize + AvailableSpace - BudgetPadding, LimitedMaxTexturePoolSize);	// Max texture pool size without going overbudget or the pre-defined max.

#Loc: <Workspace>/Engine/Source/Runtime/D3D12RHI/Private/Windows/WindowsD3D12Device.cpp:1640

Scope (from outer to inner):

file
function     void FD3D12DynamicRHI::Init

Source code excerpt:

	if (GPoolSizeVRAMPercentage > 0)
	{
		float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(FD3D12GlobalStats::GTotalGraphicsMemory);

		// Truncate GTexturePoolSize to MB (but still counted in bytes)
		GTexturePoolSize = int64(FGenericPlatformMath::TruncToFloat(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;

		UE_LOG(LogRHI, Log, TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
			GTexturePoolSize / 1024 / 1024,
			GPoolSizeVRAMPercentage,
			FD3D12GlobalStats::GTotalGraphicsMemory / 1024 / 1024);
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/AsyncTextureStreaming.cpp:572

Scope (from outer to inner):

file
function     void FRenderAssetStreamingMipCalcTask::UpdateBudgetedMips_Async

Source code excerpt:


	const int64 NonStreamingRenderAssetMemory =  AllocatedMemory - MemoryUsed + MemoryUsedByNonTextures;
	int64 AvailableMemoryForStreaming = PoolSize - NonStreamingRenderAssetMemory - MemoryMargin;

	// If the platform defines a max VRAM usage, check if the pool size must be reduced,
	// but also check if it would be safe to some of the NonStreamingRenderAssetMemory from the pool size computation.
	// The later helps significantly in low budget settings, where NonStreamingRenderAssetMemory would take too much of the pool.
	if (GPoolSizeVRAMPercentage > 0 && TotalGraphicsMemory > 0)
	{
		const int64 UsableVRAM = FMath::Max<int64>(TotalGraphicsMemory * GPoolSizeVRAMPercentage / 100, TotalGraphicsMemory - Settings.VRAMPercentageClamp * 1024ll * 1024ll);
		const int64 UsedVRAM = (int64)GRHIGlobals.NonStreamingTextureMemorySizeInKB * 1024ll + NonStreamingRenderAssetMemory; // Add any other...
		const int64 AvailableVRAMForStreaming = FMath::Min<int64>(UsableVRAM - UsedVRAM - MemoryMargin, PoolSize);
		if (Settings.bLimitPoolSizeToVRAM || AvailableVRAMForStreaming > AvailableMemoryForStreaming)
		{
			AvailableMemoryForStreaming = AvailableVRAMForStreaming;
		}
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/AsyncTextureStreaming.cpp:943

Scope (from outer to inner):

file
function     void FRenderAssetStreamingMipCalcTask::UpdateStats_Async

Source code excerpt:

	TArray<FStreamingRenderAsset>& StreamingRenderAssets = StreamingManager.AsyncUnsafeStreamingRenderAssets;

	Stats.RenderAssetPool = PoolSize;
	// Stats.StreamingPool = MemoryBudget;
	Stats.UsedStreamingPool = 0;

	Stats.SafetyPool = MemoryMargin; 
	Stats.TemporaryPool = TempMemoryBudget;
	Stats.StreamingPool = MemoryBudget;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/AsyncTextureStreaming.cpp:1081

Scope (from outer to inner):

file
function     void FRenderAssetStreamingMipCalcTask::UpdateCSVOnlyStats_Async

Source code excerpt:

	FRenderAssetStreamingStats& Stats = StreamingManager.GatheredStats;

	Stats.RenderAssetPool = PoolSize;

	Stats.SafetyPool = MemoryMargin;
	Stats.TemporaryPool = TempMemoryBudget;
	Stats.StreamingPool = MemoryBudget;
	Stats.NonStreamingMips = AllocatedMemory;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/AsyncTextureStreaming.h:146

Scope (from outer to inner):

file
class        class FRenderAssetStreamingMipCalcTask : public FNonAbandonableTask
function     void Reset

Source code excerpt:

		TotalGraphicsMemory = InTotalGraphicsMemory;
		AllocatedMemory = InAllocatedMemory;
		PoolSize = InPoolSize;
		TempMemoryBudget = InTempMemoryBudget;
		MemoryMargin = InMemoryMargin;

		bAbort = false;
	}

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/AsyncTextureStreaming.h:228

Scope (from outer to inner):

file
class        class FRenderAssetStreamingMipCalcTask : public FNonAbandonableTask

Source code excerpt:


	/** Size of the pool once non streaming data is removed and value is stabilized */
	int64 PoolSize;

	/** How much temp memory is allowed (temp memory is taken when changing mip count). */
	int64 TempMemoryBudget;

	/** How much temp memory is allowed (temp memory is taken when changing mip count). */
	int64 MemoryMargin;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/StreamingManagerTexture.cpp:135

Scope (from outer to inner):

file
function     FRenderAssetStreamingManager::FRenderAssetStreamingManager

Source code excerpt:


	int32 PoolSizeIniSetting = 0;
	GConfig->GetInt(TEXT("TextureStreaming"), TEXT("PoolSize"), PoolSizeIniSetting, GEngineIni);
	GConfig->GetBool(TEXT("TextureStreaming"), TEXT("UseDynamicStreaming"), bUseDynamicStreaming, GEngineIni);
	GConfig->GetFloat( TEXT("TextureStreaming"), TEXT("BoostPlayerTextures"), BoostPlayerTextures, GEngineIni );
	GConfig->GetBool(TEXT("TextureStreaming"), TEXT("NeverStreamOutRenderAssets"), GNeverStreamOutRenderAssets, GEngineIni);

	// -NeverStreamOutRenderAssets
	if (FParse::Param(FCommandLine::Get(), TEXT("NeverStreamOutRenderAssets")))

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/TextureStreamingHelpers.cpp:311

Scope (from outer to inner):

file
function     void FRenderAssetStreamingSettings::Update

Source code excerpt:

	HLODStrategy = CVarStreamingHLODStrategy.GetValueOnAnyThread();
	GlobalMipBias = !GIsEditor ? FMath::FloorToInt(FMath::Max<float>(0.f, CVarStreamingMipBias.GetValueOnAnyThread())) : 0;
	PoolSize = CVarStreamingPoolSize.GetValueOnAnyThread();
	MeshPoolSize = CVarStreamingPoolSizeForMeshes.GetValueOnAnyThread();
	bUsePerTextureBias = CVarStreamingUsePerTextureBias.GetValueOnAnyThread() != 0;
	bUseNewMetrics = CVarStreamingUseNewMetrics.GetValueOnAnyThread() != 0;
	bLimitPoolSizeToVRAM = !GIsEditor && CVarStreamingLimitPoolSizeToVRAM.GetValueOnAnyThread() != 0;
	bFullyLoadUsedTextures = CVarStreamingFullyLoadUsedTextures.GetValueOnAnyThread() != 0;
	bFullyLoadMeshes = CVarStreamingFullyLoadMeshes.GetValueOnAnyThread() != 0;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/TextureStreamingHelpers.h:99

Scope: file

Source code excerpt:

	float MaxHiddenPrimitiveViewBoost;
	int32 GlobalMipBias;
	int32 PoolSize;
	int32 MeshPoolSize;
	bool bLimitPoolSizeToVRAM;
	bool bUseNewMetrics;
	bool bFullyLoadUsedTextures;
	bool bFullyLoadMeshes;
	bool bUseAllMips;

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapeEditReadback.cpp:235

Scope (from outer to inner):

file
class        class FLandscapeEditReadbackTaskPool : public FRenderResource
function     void GarbageCollect

Source code excerpt:

	void GarbageCollect()
	{
		const uint32 PoolSize = Pool.Num();
		if (PoolSize > 0)
		{
			// Garbage collect a maximum of one item per call to reduce overhead if pool has grown large.
			FLandscapeEditReadbackTaskImpl* Task = &Pool[FrameCount % PoolSize];
			if (Task->InitFrameId + 100 < FrameCount)
			{
				if (Task->TextureResource != nullptr)
				{
					// Task not completed after 100 updates. We are probably leaking tasks!
					UE_LOG(LogLandscape, Warning, TEXT("Leaking landscape edit layer read back tasks."))

#Loc: <Workspace>/Engine/Source/Runtime/Landscape/Private/LandscapePhysicalMaterial.cpp:507

Scope (from outer to inner):

file
class        class FLandscapePhysicalMaterialRenderTaskPool : public FRenderResource
function     void GarbageCollect

Source code excerpt:

	void GarbageCollect()
	{
		const uint32 PoolSize = Pool.Num();
		if (PoolSize > 0)
		{
			// Garbage collect a maximum of one item per call to reduce overhead if pool has grown large.
			FLandscapePhysicalMaterialRenderTaskImpl* Task = &Pool[FrameCount % PoolSize];

			// Only garbage collect tasks that are at least 100 frames old (allows resources to be re-used for some time)
			if (Task->InitFrameId + 100 < FrameCount)
			{
				if (Task->LandscapeComponent != nullptr)
				{

#Loc: <Workspace>/Engine/Source/Runtime/OpenGLDrv/Private/OpenGLDevice.cpp:1473

Scope (from outer to inner):

file
function     void FOpenGLDynamicRHI::Init

Source code excerpt:

		if ( GPoolSizeVRAMPercentage > 0 )
		{
			float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(GOpenGLTotalGraphicsMemory);

			// Truncate GTexturePoolSize to MB (but still counted in bytes)
			GTexturePoolSize = int64(FGenericPlatformMath::TruncToInt(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;

			UE_LOG(LogRHI, Log, TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
				GTexturePoolSize / 1024 / 1024,
				GPoolSizeVRAMPercentage,
				GOpenGLTotalGraphicsMemory / 1024 / 1024);
		}

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Private/RHICoreTransientResourceAllocator.cpp:1296

Scope (from outer to inner):

file
function     FRHITransientPagePool* FRHITransientPagePoolCache::Acquire

Source code excerpt:

	PagePoolInitializer.PageSize = Initializer.PageSize;

	if (LiveList.IsEmpty() && Initializer.PoolSizeFirst > Initializer.PoolSize)
	{
		PagePoolInitializer.PageCount = Initializer.PoolSizeFirst / Initializer.PageSize;
	}
	else
	{
		PagePoolInitializer.PageCount = Initializer.PoolSize / Initializer.PageSize;
	}

	FRHITransientPagePool* PagePool = CreatePagePool(PagePoolInitializer);
	check(PagePool);

	TotalMemoryCapacity += PagePool->GetCapacity();

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Private/RHIPoolAllocator.cpp:278

Scope (from outer to inner):

file
function     FRHIMemoryPool::FRHIMemoryPool

Source code excerpt:

FRHIMemoryPool::FRHIMemoryPool(int16 InPoolIndex, uint64 InPoolSize, uint32 InPoolAlignment, ERHIPoolResourceTypes InSupportedResourceTypes, EFreeListOrder InFreeListOrder) :
	PoolIndex(InPoolIndex), 
	PoolSize(InPoolSize), 
	PoolAlignment(InPoolAlignment),
	SupportedResourceTypes(InSupportedResourceTypes),
	FreeListOrder(InFreeListOrder),
	FreeSize(0), 
	AligmnentWaste(0), 
	AllocatedBlocks(0)
{	
	// PoolSize should fit in 32 bits because FRHIPoolAllocationData only stores 32bit size
	check(PoolSize < UINT32_MAX);
}


FRHIMemoryPool::~FRHIMemoryPool()
{
	// Can't currently validate because Engine is still leaking too much during shutdown sadly enough

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Private/RHIPoolAllocator.cpp:297

Scope (from outer to inner):

file
function     FRHIMemoryPool::~FRHIMemoryPool

Source code excerpt:

	check(AllocatedBlocks == 0);
	check(AligmnentWaste == 0);
	check(FreeSize == PoolSize);
	check(FreeBlocks.Num() == 1);
	check(FreeBlocks[0]->GetSize() == PoolSize);
	*/

	Validate();
}


void FRHIMemoryPool::Init()
{
	FreeSize = PoolSize;

	// Setup a few working free blocks	
	AllocationDataPool.Reserve(DesiredAllocationPoolSize);
	for (int32 Index = 0; Index < DesiredAllocationPoolSize; ++Index)
	{
		FRHIPoolAllocationData* AllocationData = new FRHIPoolAllocationData();

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Private/RHIPoolAllocator.cpp:322

Scope (from outer to inner):

file
function     void FRHIMemoryPool::Init

Source code excerpt:

	HeadBlock.InitAsHead(PoolIndex);
	FRHIPoolAllocationData* FreeBlock = GetNewAllocationData();
	FreeBlock->InitAsFree(PoolIndex, PoolSize, PoolAlignment, 0);
	HeadBlock.AddAfter(FreeBlock);
	FreeBlocks.Add(FreeBlock);

	Validate();
}

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Private/RHIPoolAllocator.cpp:614

Scope (from outer to inner):

file
function     void FRHIMemoryPool::Validate

Source code excerpt:

	}

	check(TotalFreeSize + TotalAllocatedSize == PoolSize);
	check(TotalFreeSize == FreeSize);
	check(TotalAllocatedSize == GetUsedSize());

	// Validate the free blocks
	TotalFreeSize = 0;
	for (int32 FreeBlockIndex = 0; FreeBlockIndex < FreeBlocks.Num(); ++FreeBlockIndex)

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Public/RHICoreTransientResourceAllocator.h:979

Scope (from outer to inner):

file
class        class FRHITransientPagePoolCache : public IRHITransientMemoryCache

Source code excerpt:


		// Size in bytes of the pool. Must be a multiple of PageSize.
		uint64 PoolSize = 0;

		// Size in bytes of the first pool. Only takes effect if larger than PoolSize.
		uint64 PoolSizeFirst = 0;

		// Size of each page.
		uint32 PageSize = 0;

		// The latency between the completed fence value and the used fence value to invoke garbage collection of the heap.

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Public/RHIPoolAllocator.h:156

Scope (from outer to inner):

file
class        class FRHIMemoryPool
function     uint64 GetPoolSize

Source code excerpt:

	// Getters
	int16 GetPoolIndex() const { return PoolIndex; }
	uint64 GetPoolSize() const { return PoolSize; }
	uint64 GetFreeSize() const { return FreeSize; }
	uint64 GetUsedSize() const { return (PoolSize - FreeSize); }
	uint32 GetAlignmentWaste() const { return AligmnentWaste; }
	uint32 GetAllocatedBlocks() const { return AllocatedBlocks; }
	ERHIPoolResourceTypes GetSupportedResourceTypes() const { return SupportedResourceTypes; }
	bool IsResourceTypeSupported(ERHIPoolResourceTypes InType) const { return EnumHasAnyFlags(SupportedResourceTypes, InType); }
	bool IsEmpty() const { return GetUsedSize() == 0; }
	bool IsFull() const { return FreeSize == 0; }

#Loc: <Workspace>/Engine/Source/Runtime/RHICore/Public/RHIPoolAllocator.h:186

Scope (from outer to inner):

file
class        class FRHIMemoryPool

Source code excerpt:

	// Const creation members
	int16 PoolIndex;
	const uint64 PoolSize;
	const uint32 PoolAlignment;
	const ERHIPoolResourceTypes SupportedResourceTypes;
	const EFreeListOrder FreeListOrder;

	// Stats
	uint64 FreeSize;

#Loc: <Workspace>/Engine/Source/Runtime/SlateCore/Private/Fonts/SlateSdfGenerator.cpp:546

Scope (from outer to inner):

file
function     bool FSlateSdfGeneratorImpl::UpdatePoolSize

Source code excerpt:

{
	check(IsInGameThread());
	int32 PoolSize = 0;
	if (IsSlateSdfTextFeatureEnabled())
	{
		PoolSize = CVarSlateSdfTextGeneratorPoolSize.GetValueOnGameThread();
		if (PoolSize <= 0)
		{
			PoolSize = FGenericPlatformMisc::NumberOfWorkerThreadsToSpawn();
		}
	}
	int32 OldPoolSize = TasksPool.Num();
	if (PoolSize < OldPoolSize)
	{
		return false;
	}
	if (PoolSize > OldPoolSize)
	{
		FreeTasks.Reserve(PoolSize);
		StartedTasks.Reserve(PoolSize);
		TasksPool.Reserve(PoolSize);
		for (int32 Index = OldPoolSize; Index < PoolSize; ++Index)
		{
			int32 AddedIndex = TasksPool.Add(MakeUnique<FAsyncTask<SdfUtils::FSdfGeneratorTask>>());
			check(AddedIndex == Index);
			FreeTasks.Push(TasksPool[AddedIndex].Get());
		}
	}

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanCommandBuffer.cpp:282

Scope (from outer to inner):

file
function     inline void FVulkanCmdBuffer::InitializeTimings

Source code excerpt:

			// Upload cb's can be submitted multiple times in a single frame, so we use an expanded pool to catch timings
			// Any overflow will wrap
			const uint32 PoolSize = bIsUploadOnly ? 256 : 32;
			Timing->Initialize(PoolSize);
		}
	}
}

void FVulkanCmdBuffer::AddWaitSemaphore(VkPipelineStageFlags InWaitFlags, TArrayView<VulkanRHI::FSemaphore*> InWaitSemaphores)
{

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanGPUProfiler.h:47

Scope (from outer to inner):

file
class        class FVulkanGPUTiming : public FGPUTiming

Source code excerpt:

	 * Initializes all Vulkan resources.
	 */
	void Initialize(uint32 PoolSize = 8);

	/**
	 * Releases all Vulkan resources.
	 */
	void Release();

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanMemory.cpp:2730

Scope (from outer to inner):

file
function     bool FMemoryManager::AllocateBufferPooled

Source code excerpt:

		const float Priority = CalculateBufferPriority(BufferUsageFlags);

		const int32 PoolSize = (int32)GetPoolTypeForAlloc(Size, Alignment);
		if (PoolSize != (int32)EPoolSizes::SizesCount)
		{
			Size = PoolSizes[PoolSize];
		}

		FScopeLock ScopeLock(&UsedFreeBufferAllocationsLock);

		for (int32 Index = 0; Index < UsedBufferAllocations[PoolSize].Num(); ++Index)
		{
			FVulkanSubresourceAllocator* SubresourceAllocator = UsedBufferAllocations[PoolSize][Index];
			if ((SubresourceAllocator->BufferUsageFlags & BufferUsageFlags) == BufferUsageFlags &&
				(SubresourceAllocator->MemoryPropertyFlags & MemoryPropertyFlags) == MemoryPropertyFlags)
			{

				if(SubresourceAllocator->TryAllocate2(OutAllocation, AllocationOwner, Size, Alignment, MetaType, File, Line))
				{

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanMemory.cpp:2753

Scope (from outer to inner):

file
function     bool FMemoryManager::AllocateBufferPooled

Source code excerpt:

		}

		for (int32 Index = 0; Index < FreeBufferAllocations[PoolSize].Num(); ++Index)
		{
			FVulkanSubresourceAllocator* SubresourceAllocator = FreeBufferAllocations[PoolSize][Index];
			if ((SubresourceAllocator->BufferUsageFlags & BufferUsageFlags) == BufferUsageFlags &&
				(SubresourceAllocator->MemoryPropertyFlags & MemoryPropertyFlags) == MemoryPropertyFlags)
			{
				if(SubresourceAllocator->TryAllocate2(OutAllocation, AllocationOwner, Size, Alignment, MetaType, File, Line))
				{
					IncMetaStats(MetaType, OutAllocation.Size);
					FreeBufferAllocations[PoolSize].RemoveAtSwap(Index, 1, EAllowShrinking::No);
					UsedBufferAllocations[PoolSize].Add(SubresourceAllocator);
					return true;
				}
			}
		}

		// New Buffer
		const uint32 BufferSize = FMath::Max(Size, BufferSizes[PoolSize]);

		VkBuffer Buffer;
		VkBufferCreateInfo BufferCreateInfo;
		ZeroVulkanStruct(BufferCreateInfo, VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO);
		BufferCreateInfo.size = BufferSize;
		BufferCreateInfo.usage = BufferUsageFlags;

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanMemory.cpp:2825

Scope (from outer to inner):

file
function     bool FMemoryManager::AllocateBufferPooled

Source code excerpt:

		}
		FVulkanSubresourceAllocator* SubresourceAllocator = new FVulkanSubresourceAllocator(EVulkanAllocationPooledBuffer, this, AllocationFlags, DeviceMemoryAllocation, MemoryTypeIndex,
			MemoryPropertyFlags, MemReqs.alignment, Buffer, BufferSize, BufferId, BufferUsageFlags, PoolSize);

		RegisterSubresourceAllocator(SubresourceAllocator);
		UsedBufferAllocations[PoolSize].Add(SubresourceAllocator);

		if(SubresourceAllocator->TryAllocate2(OutAllocation, AllocationOwner, Size, Alignment, MetaType, File, Line))
		{
			IncMetaStats(MetaType, OutAllocation.Size);
			return true;
		}

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanMemory.cpp:3399

Scope (from outer to inner):

file
function     void FMemoryManager::DumpMemory

Source code excerpt:

			{
				int PoolSizeIndex = (Index - NumResourceHeaps) % NumSmallAllocators;
				uint32 PoolSize = PoolSizeIndex >= (int32)EPoolSizes::SizesCount ? -1 : PoolSizes[PoolSizeIndex];
				if(0 == PoolSizeIndex)
				{
					VULKAN_LOGMEMORY(VULKAN_LOGMEMORY_PAD);
				}
				WriteLogLine(FString::Printf(TEXT("Pool %d"), PoolSize), Stat);
			}
			else
			{
				WriteLogLine(FString::Printf(TEXT("ResourceHeap %d"), Index), Stat);
			}
		}

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanMemory.h:859

Scope (from outer to inner):

file
namespace    VulkanRHI
class        class FMemoryManager : public FDeviceChild
function     EPoolSizes GetPoolTypeForAlloc

Source code excerpt:

		EPoolSizes GetPoolTypeForAlloc(uint32 Size, uint32 Alignment)
		{
			EPoolSizes PoolSize = EPoolSizes::SizesCount;
			if (GVulkanUseBufferBinning != 0)
			{
				for (int32 i = 0; i < (int32)EPoolSizes::SizesCount; ++i)
				{
					if (PoolSizes[i] >= Size)
					{
						PoolSize = (EPoolSizes)i;
						break;
					}
				}
			}
			return PoolSize;
		}

		FCriticalSection UsedFreeBufferAllocationsLock;
		TArray<FVulkanSubresourceAllocator*> UsedBufferAllocations[(int32)EPoolSizes::SizesCount + 1];
		TArray<FVulkanSubresourceAllocator*> FreeBufferAllocations[(int32)EPoolSizes::SizesCount + 1];

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanRHI.cpp:553

Scope (from outer to inner):

file
function     void FVulkanDynamicRHI::Init

Source code excerpt:

		const uint64 TotalGPUMemory = Device->GetDeviceMemoryManager().GetTotalMemory(true);

		float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(TotalGPUMemory);

		// Truncate GTexturePoolSize to MB (but still counted in bytes)
		GTexturePoolSize = int64(FGenericPlatformMath::TruncToFloat(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;

		UE_LOG(LogRHI, Log, TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
			GTexturePoolSize / 1024 / 1024,
			GPoolSizeVRAMPercentage,
			TotalGPUMemory / 1024 / 1024);
	}

#Loc: <Workspace>/Engine/Source/Runtime/VulkanRHI/Private/VulkanUtil.cpp:166

Scope (from outer to inner):

file
function     void FVulkanGPUTiming::Initialize

Source code excerpt:

 * Initializes all Vulkan resources and if necessary, the static variables.
 */
void FVulkanGPUTiming::Initialize(uint32 PoolSize)
{
	StaticInitialize(this, PlatformStaticInitialize);

	bIsTiming = false;

	if (FVulkanPlatform::SupportsTimestampRenderQueries() && GIsSupported)
	{
		check(!Pool);
		Pool = new FVulkanTimingQueryPool(Device, CmdContext->GetCommandBufferManager(), PoolSize);
		Pool->ResultsBuffer = Device->GetStagingManager().AcquireBuffer(Pool->GetMaxQueries() * sizeof(uint64) * 2, VK_BUFFER_USAGE_TRANSFER_DST_BIT, VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
		Pool->MappedPointer = (uint64*)Pool->ResultsBuffer->GetMappedPointer();
	}
}

/**

#Loc: <Workspace>/Engine/Source/Runtime/Windows/D3D11RHI/Private/Windows/WindowsD3D11Device.cpp:1737

Scope (from outer to inner):

file
function     void FD3D11DynamicRHI::InitD3DDevice

Source code excerpt:

		if ( GPoolSizeVRAMPercentage > 0 )
		{
			float PoolSize = float(GPoolSizeVRAMPercentage) * 0.01f * float(FD3D11GlobalStats::GTotalGraphicsMemory);

			// Truncate GTexturePoolSize to MB (but still counted in bytes)
			GTexturePoolSize = int64(FGenericPlatformMath::TruncToFloat(PoolSize / 1024.0f / 1024.0f)) * 1024 * 1024;

			UE_LOG(LogRHI,Log,TEXT("Texture pool is %llu MB (%d%% of %llu MB)"),
				GTexturePoolSize / 1024 / 1024,
				GPoolSizeVRAMPercentage,
				FD3D11GlobalStats::GTotalGraphicsMemory / 1024 / 1024);
		}