geometry.DynamicMesh.MaxPoolSize

geometry.DynamicMesh.MaxPoolSize

#Overview

name: geometry.DynamicMesh.MaxPoolSize

This variable is created as a Console Variable (cvar).

It is referenced in 4 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of geometry.DynamicMesh.MaxPoolSize is to set a threshold for the maximum number of meshes that a UDynamicMeshPool will allow in its pool before triggering garbage collection. This setting is part of Unreal Engine 5’s geometry system, specifically for managing dynamic meshes.

The Unreal Engine subsystem that relies on this setting variable is the GeometryFramework module, which is responsible for handling dynamic mesh operations and management.

The value of this variable is set as a console variable (CVar) with a default value of 1000. It can be modified at runtime through console commands or configuration files.

This variable interacts directly with its associated variable CVarDynamicMeshPoolMaxPoolSizeThreshold, which is used in the C++ code to access the value set by geometry.DynamicMesh.MaxPoolSize.

Developers must be aware that this variable acts as a safety mechanism to prevent potential memory leaks. If the number of allocated meshes exceeds this threshold, the UDynamicMeshPool will release all its references and force garbage collection on the next call to RequestMesh().

Best practices when using this variable include:

  1. Monitoring the number of dynamic meshes in use to ensure it doesn’t frequently exceed the threshold.
  2. Adjusting the value based on the specific needs of the project and available memory.
  3. Ensuring proper mesh management by calling ReturnMesh() when a mesh is no longer needed.

Regarding the associated variable CVarDynamicMeshPoolMaxPoolSizeThreshold:

The purpose of CVarDynamicMeshPoolMaxPoolSizeThreshold is to provide a runtime-accessible representation of the geometry.DynamicMesh.MaxPoolSize setting within the C++ code.

This variable is used directly in the UDynamicMeshPool::RequestMesh() function to check if the number of allocated meshes has exceeded the threshold. If exceeded, it triggers the release of references and forces garbage collection.

The value of this variable is set by the console variable system based on the geometry.DynamicMesh.MaxPoolSize setting.

Developers should be aware that modifying this variable directly in code is not recommended, as it should reflect the value set by the geometry.DynamicMesh.MaxPoolSize console variable.

Best practices for using this variable include:

  1. Using GetValueOnGameThread() to access its current value in gameplay code.
  2. Avoid directly modifying this variable; instead, change the geometry.DynamicMesh.MaxPoolSize console variable if adjustments are needed.
  3. Consider logging or alerting when the threshold is reached to help identify potential mesh management issues in the game.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/GeometryFramework/Private/UDynamicMesh.cpp:559

Scope: file

Source code excerpt:


static TAutoConsoleVariable<int32> CVarDynamicMeshPoolMaxPoolSizeThreshold(
	TEXT("geometry.DynamicMesh.MaxPoolSize"),
	1000,
	TEXT("Maximum number of meshes a UDynamicMeshPool will allow to be in the pool before running garbage collection"));



UDynamicMesh* UDynamicMeshPool::RequestMesh()

#Loc: <Workspace>/Engine/Source/Runtime/GeometryFramework/Public/UDynamicMesh.h:351

Scope: file

Source code excerpt:

 * If you Request() more meshes than you Return(), the Pool will still be holding on to
 * references to those meshes, and they will never be Garbage Collected (ie memory leak).
 * As a failsafe, if the number of allocated meshes exceeds geometry.DynamicMesh.MaxPoolSize,
 * the Pool will release all it's references and run garbage collection on the next call to RequestMesh().
 * (Do not rely on this as a memory management strategy)
 *
 * An alternate strategy that could be employed here is for the Pool to not hold
 * references to meshes it has provided, only those that have been explicitly returned.
 * Then non-returned meshes would simply be garbage-collected, however it allows
 * potentially a large amount of memory to be consumed until that occurs.
 *
 * UDynamicMesh::Reset() is called on the object returned to the Pool, which clears
 * the internal FDynamicMesh3 (which uses normal C++ memory management, so no garbage collection involved)
 * So the Pool does not re-use mesh memory, only the UObject containers.
 */
UCLASS(BlueprintType, Transient, MinimalAPI)
class UDynamicMeshPool : public UObject
{
	GENERATED_BODY()
public:
	/** @return an available UDynamicMesh from the pool (possibly allocating a new mesh) */
	UFUNCTION(BlueprintCallable, Category="Dynamic Mesh")
	GEOMETRYFRAMEWORK_API UDynamicMesh* RequestMesh();

	/** Release a UDynamicMesh returned by RequestMesh() back to the pool */
	UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh")
	GEOMETRYFRAMEWORK_API void ReturnMesh(UDynamicMesh* Mesh);

	/** Release all GeneratedMeshes back to the pool */
	UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh")
	GEOMETRYFRAMEWORK_API void ReturnAllMeshes();

	/** Release all GeneratedMeshes back to the pool and allow them to be garbage collected */
	UFUNCTION(BlueprintCallable, Category = "Dynamic Mesh")
	GEOMETRYFRAMEWORK_API void FreeAllMeshes();

protected:
	/** Meshes in the pool that are available */
	UPROPERTY()
	TArray<TObjectPtr<UDynamicMesh>> CachedMeshes;

	/** All meshes the pool has allocated */
	UPROPERTY()

#Associated Variable and Callsites

This variable is associated with another variable named CVarDynamicMeshPoolMaxPoolSizeThreshold. They share the same value. See the following C++ source code.

#Loc: <Workspace>/Engine/Source/Runtime/GeometryFramework/Private/UDynamicMesh.cpp:558

Scope: file

Source code excerpt:

//

static TAutoConsoleVariable<int32> CVarDynamicMeshPoolMaxPoolSizeThreshold(
	TEXT("geometry.DynamicMesh.MaxPoolSize"),
	1000,
	TEXT("Maximum number of meshes a UDynamicMeshPool will allow to be in the pool before running garbage collection"));

#Loc: <Workspace>/Engine/Source/Runtime/GeometryFramework/Private/UDynamicMesh.cpp:575

Scope (from outer to inner):

file
function     UDynamicMesh* UDynamicMeshPool::RequestMesh

Source code excerpt:

	// If we have allocated more meshes than our safety threshold, drop our holds on the existing meshes.
	// This will allow them to be garbage-collected (eventually)
	if (!ensure(AllCreatedMeshes.Num() < CVarDynamicMeshPoolMaxPoolSizeThreshold.GetValueOnGameThread()))
	{
		UE_LOG(LogGeometry, Warning, TEXT("UDynamicMeshPool Threshold of %d Allocated Meshes exceeded! Releasing references to all current meshes and forcing a garbage collection."), CVarDynamicMeshPoolMaxPoolSizeThreshold.GetValueOnGameThread());
		AllCreatedMeshes.Reset();
		GEngine->ForceGarbageCollection(true);
	}

	AllCreatedMeshes.Add(NewMesh);
	return NewMesh;