r.InstancedStaticMeshes.ForceRemoveAtSwap

r.InstancedStaticMeshes.ForceRemoveAtSwap

#Overview

name: r.InstancedStaticMeshes.ForceRemoveAtSwap

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 r.InstancedStaticMeshes.ForceRemoveAtSwap is to control the optimization method used when removing instances from an Instanced Static Mesh (ISM). It is primarily used in the rendering system, specifically for managing instanced static meshes.

This setting variable is used within the Engine module, particularly in the InstancedStaticMesh component. It affects how instances are removed from an Instanced Static Mesh, which is a crucial part of the rendering and performance optimization in Unreal Engine 5.

The value of this variable is set through the console variable system. It’s initialized with a default value of 0, meaning the optimization is not forced by default.

The associated variable CVarISMForceRemoveAtSwap directly interacts with r.InstancedStaticMeshes.ForceRemoveAtSwap. They share the same value and purpose.

Developers must be aware that enabling this variable (setting it to a non-zero value) will force the use of the RemoveAtSwap optimization when removing instances from an ISM. This can have implications on instance indexing and performance.

Best practices when using this variable include:

  1. Understanding the trade-offs between using RemoveAtSwap and standard removal methods.
  2. Testing thoroughly when enabling this optimization, as it may affect existing code that relies on specific instance indexing behavior.
  3. Using this in conjunction with the bSupportRemoveAtSwap property of the UInstancedStaticMeshComponent for more granular control.

Regarding the associated variable CVarISMForceRemoveAtSwap:

This is the actual console variable that controls the behavior described above. It’s defined using TAutoConsoleVariable, which allows it to be changed at runtime through console commands.

The purpose of CVarISMForceRemoveAtSwap is identical to r.InstancedStaticMeshes.ForceRemoveAtSwap - it forces the use of the RemoveAtSwap optimization when removing instances from an ISM.

This variable is used in the Engine module, specifically in the InstancedStaticMesh component implementation.

The value is set when the console variable is defined, with a default of 0. It can be changed at runtime using console commands.

CVarISMForceRemoveAtSwap interacts directly with the InstancedStaticMesh component’s behavior, affecting methods like SupportsRemoveSwap() and RemoveInstanceInternal().

Developers should be aware that this variable can be changed at runtime, which could lead to different behavior in debug versus release builds if not managed carefully.

Best practices include:

  1. Using this variable for performance testing and optimization.
  2. Considering the implications on existing code that might rely on specific instance removal behavior.
  3. Documenting any use of this variable in project settings or documentation to ensure consistent behavior across different development environments.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:176

Scope: file

Source code excerpt:


static TAutoConsoleVariable<int32> CVarISMForceRemoveAtSwap(
	TEXT("r.InstancedStaticMeshes.ForceRemoveAtSwap"),
	0,
	TEXT("Force the RemoveAtSwap optimization when removing instances from an ISM."));

static TAutoConsoleVariable<int32> CVarISMFetchInstanceCountFromScene(
	TEXT("r.InstancedStaticMeshes.FetchInstanceCountFromScene"),
	1,

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:175

Scope: file

Source code excerpt:

#endif

static TAutoConsoleVariable<int32> CVarISMForceRemoveAtSwap(
	TEXT("r.InstancedStaticMeshes.ForceRemoveAtSwap"),
	0,
	TEXT("Force the RemoveAtSwap optimization when removing instances from an ISM."));

static TAutoConsoleVariable<int32> CVarISMFetchInstanceCountFromScene(
	TEXT("r.InstancedStaticMeshes.FetchInstanceCountFromScene"),

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:3420

Scope (from outer to inner):

file
function     bool UInstancedStaticMeshComponent::SupportsRemoveSwap

Source code excerpt:

bool UInstancedStaticMeshComponent::SupportsRemoveSwap() const
{
	return bSupportRemoveAtSwap || CVarISMForceRemoveAtSwap.GetValueOnGameThread() != 0;
}

bool UInstancedStaticMeshComponent::RemoveInstanceInternal(int32 InstanceIndex, bool InstanceAlreadyRemoved, bool bForceRemoveAtSwap, const bool bUpdateNavigation)
{
#if WITH_EDITOR
	DeletionState = InstanceAlreadyRemoved ? EInstanceDeletionReason::EntryAlreadyRemoved : EInstanceDeletionReason::EntryRemoval;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/InstancedStaticMesh.cpp:3431

Scope (from outer to inner):

file
function     bool UInstancedStaticMeshComponent::RemoveInstanceInternal

Source code excerpt:

	// For performance we would prefer to use RemoveAtSwap() but some old code may be relying on the old
	// RemoveAt() behavior, since there was no explicit contract about how instance indices can move around.
	const bool bUseRemoveAtSwap = bForceRemoveAtSwap || bSupportRemoveAtSwap || CVarISMForceRemoveAtSwap.GetValueOnGameThread() != 0;
	if (bUseRemoveAtSwap)
	{
		PrimitiveInstanceDataManager.RemoveAtSwap(InstanceIndex);
	}
	else
	{