p.Chaos.XPBDSpring.ParallelConstraintCount

p.Chaos.XPBDSpring.ParallelConstraintCount

#Overview

name: p.Chaos.XPBDSpring.ParallelConstraintCount

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

It is referenced in 12 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of p.Chaos.XPBDSpring.ParallelConstraintCount is to determine when to use parallel processing for XPBD (Extended Position Based Dynamics) spring constraints in the Chaos physics engine of Unreal Engine 5. It sets a threshold for the number of constraints that, when exceeded, triggers parallel computation.

This setting variable is primarily used in the Chaos physics engine, specifically in the XPBD spring constraint system. It’s part of the Experimental Chaos module in Unreal Engine 5’s runtime.

The value of this variable is set to 100 by default, as seen in the source code:

int32 Chaos_XPBDSpring_ParallelConstraintCount = 100;

It’s also exposed as a console variable, allowing runtime modification:

FAutoConsoleVariableRef CVarChaosXPBDSpringParallelConstraintCount(TEXT("p.Chaos.XPBDSpring.ParallelConstraintCount"), Chaos_XPBDSpring_ParallelConstraintCount, TEXT("If we have more constraints than this, use parallel-for in Apply."));

This variable interacts closely with the constraint system, particularly in the Apply() and UpdateLinearSystem() functions of various spring constraint classes (FXPBDSpringConstraints, FXPBDAnisotropicEdgeSpringConstraints, FXPBDAnisotropicAxialSpringConstraints).

Developers should be aware that this variable affects performance and parallelism. Setting it too low might lead to unnecessary parallelization overhead for small constraint sets, while setting it too high might underutilize available parallel processing capabilities.

Best practices when using this variable include:

  1. Profiling the application to determine the optimal threshold for your specific use case.
  2. Consider the target hardware capabilities when setting this value.
  3. Be cautious when modifying this value at runtime, as it can significantly impact performance.

The associated variable Chaos_XPBDSpring_ParallelConstraintCount is used internally within the Chaos physics engine and shares the same value and purpose as p.Chaos.XPBDSpring.ParallelConstraintCount. It’s used directly in the code to check if parallel processing should be employed. The same considerations and best practices apply to this internal variable.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDSpringConstraints.cpp:30

Scope (from outer to inner):

file
namespace    Chaos::Softs

Source code excerpt:

int32 Chaos_XPBDSpring_ParallelConstraintCount = 100;
#if !UE_BUILD_SHIPPING
FAutoConsoleVariableRef CVarChaosXPBDSpringParallelConstraintCount(TEXT("p.Chaos.XPBDSpring.ParallelConstraintCount"), Chaos_XPBDSpring_ParallelConstraintCount, TEXT("If we have more constraints than this, use parallel-for in Apply."));

int32 Chaos_XPBDSpring_SplitDampingMode = (int32)EXPBDSplitDampingMode::TwoPassBefore;
FAutoConsoleVariableRef CVarChaosXPBDSpringSplitDamping(TEXT("p.Chaos.XPBDSpring.SplitDamping"), Chaos_XPBDSpring_SplitDampingMode, TEXT("Test xpbd spring split damping mode. 0 = single lambda, 1 = interleaved with damping after (non-ispc only), 2 interleaved with damping before (non-ispc only), 3 =  two passes damping after (non-ispc only), 4 = two passes damping before (default)."));
#endif

template<typename SolverParticlesOrRange>

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:23

Scope: file

Source code excerpt:


// @todo(chaos): the parallel threshold (or decision to run parallel) should probably be owned by the solver and passed to the constraint container
extern int32 Chaos_XPBDSpring_ParallelConstraintCount;

namespace Private
{
static void UpdateDists(const TArray<FSolverReal>& BaseDists, const TArray<FSolverVec2>& WarpWeftScaleBaseMultipliers, const FPBDWeightMap& WarpScale, const FPBDWeightMap& WeftScale, TArray<FSolverReal>& Dists)
{
	const bool WarpScaleHasWeightMap = WarpScale.HasWeightMap();

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:259

Scope: file

Source code excerpt:

	// In dev builds we always color so we can tune the system without restarting. See Apply()
#if UE_BUILD_SHIPPING || UE_BUILD_TEST
	if (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount)
#endif
	{
		const TArray<TArray<int32>> ConstraintsPerColor = FGraphColoring::ComputeGraphColoringParticlesOrRange(Constraints, InParticles, ParticleOffset, ParticleOffset + ParticleCount);

		// Reorder constraints based on color so each array in ConstraintsPerColor contains contiguous elements.
		TArray<TVec2<int32>> ReorderedConstraints;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:367

Scope (from outer to inner):

file
function     void FXPBDAnisotropicEdgeSpringConstraints::Apply

Source code excerpt:

	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();

	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
#if INTEL_ISPC
		if (bRealTypeCompatibleWithISPC && bChaos_XPBDSpring_ISPC_Enabled)
		{
			const bool bSingleLambda = Chaos_XPBDSpring_SplitDampingMode == (int32)EXPBDSplitDampingMode::SingleLambda;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:849

Scope (from outer to inner):

file
function     void FXPBDAnisotropicEdgeSpringConstraints::UpdateLinearSystem

Source code excerpt:

	const bool StiffnessBiasHasWeightMap = StiffnessBias.HasWeightMap();
	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();
	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
		if (!StiffnessHasWeightMap && !StiffnessWeftHasWeightMap && !StiffnessBiasHasWeightMap && !DampingHasWeightMap)
		{
			const FSolverVec3 ExpStiffnessValue((FSolverReal)StiffnessWeft, (FSolverReal)StiffnessWarp, (FSolverReal)StiffnessBias);
			const FSolverReal DampingRatioValue = (FSolverReal)DampingRatio;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:1147

Scope (from outer to inner):

file
function     void FXPBDAnisotropicAxialSpringConstraints::InitColor

Source code excerpt:

	// In dev builds we always color so we can tune the system without restarting. See Apply()
#if UE_BUILD_SHIPPING || UE_BUILD_TEST
	if (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount)
#endif
	{
		const TArray<TArray<int32>> ConstraintsPerColor = FGraphColoring::ComputeGraphColoringParticlesOrRange(Constraints, InParticles, ParticleOffset, ParticleOffset + ParticleCount);

		// Reorder constraints based on color so each array in ConstraintsPerColor contains contiguous elements.
		TArray<TVec3<int32>> ReorderedConstraints;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:1260

Scope (from outer to inner):

file
function     void FXPBDAnisotropicAxialSpringConstraints::InitColor
function     void FXPBDAnisotropicAxialSpringConstraints::Apply

Source code excerpt:

	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();

	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
#if INTEL_ISPC
		if (bRealTypeCompatibleWithISPC && bChaos_XPBDSpring_ISPC_Enabled)
		{
			const bool bSingleLambda = Chaos_XPBDSpring_SplitDampingMode == (int32)EXPBDSplitDampingMode::SingleLambda;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDAnisotropicSpringConstraints.cpp:1748

Scope (from outer to inner):

file
function     void FXPBDAnisotropicAxialSpringConstraints::InitColor
function     void FXPBDAnisotropicAxialSpringConstraints::UpdateLinearSystem

Source code excerpt:

	const bool StiffnessBiasHasWeightMap = StiffnessBias.HasWeightMap();
	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();
	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
		if (!StiffnessHasWeightMap && !StiffnessWeftHasWeightMap && !StiffnessBiasHasWeightMap && !DampingHasWeightMap)
		{
			const FSolverVec3 ExpStiffnessValue((FSolverReal)StiffnessWeft, (FSolverReal)StiffnessWarp, (FSolverReal)StiffnessBias);
			const FSolverReal DampingRatioValue = (FSolverReal)DampingRatio;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDSpringConstraints.cpp:28

Scope (from outer to inner):

file
namespace    Chaos::Softs

Source code excerpt:


// @todo(chaos): the parallel threshold (or decision to run parallel) should probably be owned by the solver and passed to the constraint container
int32 Chaos_XPBDSpring_ParallelConstraintCount = 100;
#if !UE_BUILD_SHIPPING
FAutoConsoleVariableRef CVarChaosXPBDSpringParallelConstraintCount(TEXT("p.Chaos.XPBDSpring.ParallelConstraintCount"), Chaos_XPBDSpring_ParallelConstraintCount, TEXT("If we have more constraints than this, use parallel-for in Apply."));

int32 Chaos_XPBDSpring_SplitDampingMode = (int32)EXPBDSplitDampingMode::TwoPassBefore;
FAutoConsoleVariableRef CVarChaosXPBDSpringSplitDamping(TEXT("p.Chaos.XPBDSpring.SplitDamping"), Chaos_XPBDSpring_SplitDampingMode, TEXT("Test xpbd spring split damping mode. 0 = single lambda, 1 = interleaved with damping after (non-ispc only), 2 interleaved with damping before (non-ispc only), 3 =  two passes damping after (non-ispc only), 4 = two passes damping before (default)."));
#endif

template<typename SolverParticlesOrRange>

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDSpringConstraints.cpp:41

Scope (from outer to inner):

file
namespace    Chaos::Softs
function     void FXPBDSpringConstraints::InitColor

Source code excerpt:

	// In dev builds we always color so we can tune the system without restarting. See Apply()
#if UE_BUILD_SHIPPING || UE_BUILD_TEST
	if (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount)
#endif
	{
		const TArray<TArray<int32>> ConstraintsPerColor = FGraphColoring::ComputeGraphColoringParticlesOrRange(Constraints, Particles, ParticleOffset, ParticleOffset + ParticleCount);
		
		// Reorder constraints based on color so each array in ConstraintsPerColor contains contiguous elements.
		TArray<TVec2<int32>> ReorderedConstraints;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDSpringConstraints.cpp:126

Scope (from outer to inner):

file
namespace    Chaos::Softs
function     void FXPBDSpringConstraints::Apply

Source code excerpt:

	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();

	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
#if INTEL_ISPC
		if (bRealTypeCompatibleWithISPC && bChaos_XPBDSpring_ISPC_Enabled)
		{
			const bool bSingleLambda = Chaos_XPBDSpring_SplitDampingMode == (int32)EXPBDSplitDampingMode::SingleLambda;

#Loc: <Workspace>/Engine/Source/Runtime/Experimental/Chaos/Private/Chaos/XPBDSpringConstraints.cpp:550

Scope (from outer to inner):

file
namespace    Chaos::Softs
function     void FXPBDSpringConstraints::UpdateLinearSystem

Source code excerpt:

	const bool StiffnessHasWeightMap = Stiffness.HasWeightMap();
	const bool DampingHasWeightMap = DampingRatio.HasWeightMap();
	if ((ConstraintsPerColorStartIndex.Num() > 1) && (Constraints.Num() > Chaos_XPBDSpring_ParallelConstraintCount))
	{
		const int32 ConstraintColorNum = ConstraintsPerColorStartIndex.Num() - 1;
		if (!StiffnessHasWeightMap && !DampingHasWeightMap)
		{
			const FSolverReal ExpStiffnessValue = (FSolverReal)Stiffness;
			const FSolverReal DampingRatioValue = (FSolverReal)DampingRatio;