r.Streaming.UseNewMetrics

r.Streaming.UseNewMetrics

#Overview

name: r.Streaming.UseNewMetrics

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 r.Streaming.UseNewMetrics is to control the use of an improved set of metrics and heuristics for texture streaming in Unreal Engine 5. This setting variable is primarily used in the texture streaming system, which is responsible for managing the loading and unloading of texture mip levels to optimize memory usage and performance.

The Unreal Engine subsystems that rely on this setting variable are:

  1. Texture Streaming System
  2. Rendering System
  3. Level Editor
  4. Material System

The value of this variable is set through the console variable system, with a default value of 1 (enabled). It can be changed at runtime using console commands or through code.

This variable interacts with several other variables and systems within Unreal Engine, including:

  1. Texture streaming build data
  2. Material texture streaming data
  3. Primitive component streaming
  4. Static mesh rendering
  5. Texture instance view

Developers must be aware of the following when using this variable:

  1. Enabling this variable (set to 1) activates the new metrics system, which may change the behavior of texture streaming in the engine.
  2. Some features, like the TexCoordScale accuracy view mode, require this variable to be enabled.
  3. The new metrics system uses different methods for calculating distances and bounds (AABB instead of spheres).
  4. It affects how texture streaming data is processed and how primitive distances are calculated.

Best practices when using this variable include:

  1. Generally, keep it enabled (set to 1) to benefit from the improved metrics and heuristics.
  2. When debugging texture streaming issues, consider toggling this variable to compare the behavior between the old and new systems.
  3. Ensure that texture streaming build data is up to date when using the new metrics system.
  4. Be aware that changing this variable may affect performance and memory usage, so test thoroughly in different scenarios.

Regarding the associated variable CVarStreamingUseNewMetrics:

The purpose of CVarStreamingUseNewMetrics is to provide programmatic access to the r.Streaming.UseNewMetrics console variable within the C++ code. It allows developers to check the current value of the setting and make decisions based on whether the new metrics system is enabled or not.

This variable is used throughout the engine code to conditionally execute logic related to the new metrics system. It’s particularly important in areas such as:

  1. Texture streaming calculations
  2. Render asset instance views
  3. Primitive component streaming
  4. Static mesh rendering

Developers should be aware that reading the value of CVarStreamingUseNewMetrics may have different results depending on the thread it’s called from (e.g., game thread, render thread). Always use the appropriate getter method (GetValueOnGameThread, GetValueOnRenderThread, or GetValueOnAnyThread) based on the current execution context.

Best practices for using CVarStreamingUseNewMetrics include:

  1. Use it to gate functionality that relies on the new metrics system.
  2. Be consistent in checking this variable before using new metrics-related features.
  3. Consider the performance impact of frequently checking this variable in performance-critical code paths.

#References in C++ code

#Callsites

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

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

Scope: file

Source code excerpt:


ENGINE_API TAutoConsoleVariable<int32> CVarStreamingUseNewMetrics(
	TEXT("r.Streaming.UseNewMetrics"),
	1,
	TEXT("If non-zero, will use improved set of metrics and heuristics."),
	ECVF_Default);

TAutoConsoleVariable<float> CVarStreamingBoost(
	TEXT("r.Streaming.Boost"),

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Editor/LevelEditor/Private/LevelEditorMenu.cpp:713

Scope (from outer to inner):

file
function     void FLevelEditorMenu::RegisterBuildMenu
lambda-function

Source code excerpt:

		Section.AddDynamicEntry("BuildTextureStreamingOnly", FNewToolMenuSectionDelegate::CreateLambda([](FToolMenuSection& InSection)
			{
				if (CVarStreamingUseNewMetrics.GetValueOnAnyThread() != 0) // There is no point of in building texture streaming data with the old system.
				{
					InSection.AddMenuEntry(FLevelEditorCommands::Get().BuildTextureStreamingOnly);
				}
			}));
		Section.AddMenuEntry(FLevelEditorCommands::Get().BuildVirtualTextureOnly);
	}

#Loc: <Workspace>/Engine/Source/Editor/UnrealEd/Private/SEditorViewportViewMenu.cpp:202

Scope (from outer to inner):

file
function     void SEditorViewportViewMenu::FillViewMenu
function     static void BuildOptimizationMenu

Source code excerpt:

							}
							// TexCoordScale accuracy viewmode requires shaders that are only built in the TextureStreamingBuild, which requires the new metrics to be enabled.
							if (AllowDebugViewShaderMode(DVSM_MaterialTextureScaleAccuracy, GMaxRHIShaderPlatform, FeatureLevel) && CVarStreamingUseNewMetrics.GetValueOnAnyThread() != 0 && (!InParentToolBar.IsValid() || InParentToolBar.Pin()->IsViewModeSupported(VMI_MaterialTextureScaleAccuracy)))
							{
								Section.AddMenuEntry(BaseViewportCommands.TexStreamAccMaterialTextureScaleMode, UViewModeUtils::GetViewModeDisplayName(VMI_MaterialTextureScaleAccuracy));
							}
							if (AllowDebugViewShaderMode(DVSM_RequiredTextureResolution, GMaxRHIShaderPlatform, FeatureLevel) && (!InParentToolBar.IsValid() || InParentToolBar.Pin()->IsViewModeSupported(VMI_RequiredTextureResolution)))
							{
								Section.AddMenuEntry(BaseViewportCommands.RequiredTextureResolutionMode, UViewModeUtils::GetViewModeDisplayName(VMI_RequiredTextureResolution));

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Classes/Engine/TextureStreamingTypes.h:328

Scope: file

Source code excerpt:

ENGINE_API void UnpackRelativeBox(const FBoxSphereBounds& InRefBounds, uint32 InPackedRelBox, FBoxSphereBounds& OutBounds);

extern ENGINE_API TAutoConsoleVariable<int32> CVarStreamingUseNewMetrics;
extern ENGINE_API TAutoConsoleVariable<int32> CVarFramesForFullUpdate;

/** Reset the history of the value returned by GetAverageRequiredTexturePoolSize() */
ENGINE_API void ResetAverageRequiredTexturePoolSize();

/**

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Components/PrimitiveComponent.cpp:451

Scope (from outer to inner):

file
function     void UPrimitiveComponent::GetStreamingRenderAssetInfo

Source code excerpt:

	}

	if (CVarStreamingUseNewMetrics.GetValueOnGameThread() != 0)
	{
		LevelContext.BindBuildData(nullptr);

		TArray<UMaterialInterface*> UsedMaterials;
		GetUsedMaterials(UsedMaterials);

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Materials/MaterialInterface.cpp:1596

Scope (from outer to inner):

file
function     bool UMaterialInterface::FindTextureStreamingDataIndexRange

Source code excerpt:

#endif

	if (CVarStreamingUseMaterialData.GetValueOnGameThread() == 0 || CVarStreamingUseNewMetrics.GetValueOnGameThread() == 0)
	{
		return false;
	}

	const int32 MatchingIndex = Algo::BinarySearchBy(TextureStreamingData, TextureName, &FMaterialTextureInfo::TextureName, FNameLexicalLess());
	if (MatchingIndex != INDEX_NONE)

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/PrimitiveSceneProxy.cpp:1732

Scope (from outer to inner):

file
function     bool FPrimitiveSceneProxy::GetPrimitiveDistance

Source code excerpt:

bool FPrimitiveSceneProxy::GetPrimitiveDistance(int32 LODIndex, int32 SectionIndex, const FVector& ViewOrigin, float& PrimitiveDistance) const
{
	const bool bUseNewMetrics = CVarStreamingUseNewMetrics.GetValueOnRenderThread() != 0;

	const FBoxSphereBounds& PrimBounds = GetBounds();

	FVector ViewToObject = PrimBounds.Origin - ViewOrigin;

	float DistSqMinusRadiusSq = 0;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/StaticMeshRender.cpp:897

Scope (from outer to inner):

file
function     bool FStaticMeshSceneProxy::GetPrimitiveDistance

Source code excerpt:

bool FStaticMeshSceneProxy::GetPrimitiveDistance(int32 LODIndex, int32 SectionIndex, const FVector& ViewOrigin, float& PrimitiveDistance) const
{
	const bool bUseNewMetrics = CVarStreamingUseNewMetrics.GetValueOnRenderThread() != 0;
	const float OneOverDistanceMultiplier = 1.f / FMath::Max<float>(UE_SMALL_NUMBER, StreamingDistanceMultiplier);

	if (bUseNewMetrics && LODs.IsValidIndex(LODIndex) && LODs[LODIndex].Sections.IsValidIndex(SectionIndex))
	{
		// The LOD-section data is stored per material index as it is only used for texture streaming currently.
		const int32 MaterialIndex = LODs[LODIndex].Sections[SectionIndex].MaterialIndex;

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/TextureInstanceView.cpp:171

Scope (from outer to inner):

file
function     void FRenderAssetInstanceView::FRenderAssetLinkConstIterator::OutputToLog

Source code excerpt:


	// Log the bounds
	if (CVarStreamingUseNewMetrics.GetValueOnGameThread() != 0) // New metrics uses AABB while previous metrics used spheres.
	{
		if (TexelFactor >= 0 && TexelFactor < FLT_MAX)
		{
			UE_LOG(LogContentStreaming, Log, TEXT("    Origin=(%s), BoxExtent=(%s), TexelSize=%f"), *Bounds.Origin.ToString(), *Bounds.BoxExtent.ToString(), TexelFactor);
		}
		else

#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/Streaming/TextureStreamingBuild.cpp:567

Scope (from outer to inner):

file
function     void FStreamingTextureLevelContext::BindBuildData

Source code excerpt:

	++BuildDataTimestamp;

	if (TextureGuidToLevelIndex && CVarStreamingUseNewMetrics.GetValueOnGameThread() != 0) // No point in binding data if there is no possible remapping.
	{
		// Process the build data in order to be able to map a texture object to the build data entry.
		ComponentBuildData = CanUseTextureStreamingBuiltData() ? BuildData : nullptr;
		if (BuildData && BoundStates.Num() > 0)
		{
			for (int32 Index = 0; Index < BuildData->Num(); ++Index)

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

Scope: file

Source code excerpt:

int32 FRenderAssetStreamingSettings::ExtraIOLatency = 0;

ENGINE_API TAutoConsoleVariable<int32> CVarStreamingUseNewMetrics(
	TEXT("r.Streaming.UseNewMetrics"),
	1,
	TEXT("If non-zero, will use improved set of metrics and heuristics."),
	ECVF_Default);

TAutoConsoleVariable<float> CVarStreamingBoost(

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

Scope (from outer to inner):

file
function     void FRenderAssetStreamingSettings::Update

Source code excerpt:

	MeshPoolSize = CVarStreamingPoolSizeForMeshes.GetValueOnAnyThread();
	bUsePerTextureBias = CVarStreamingUsePerTextureBias.GetValueOnAnyThread() != 0;
	bUseNewMetrics = CVarStreamingUseNewMetrics.GetValueOnAnyThread() != 0;
	bLimitPoolSizeToVRAM = !GIsEditor && CVarStreamingLimitPoolSizeToVRAM.GetValueOnAnyThread() != 0;
	bFullyLoadUsedTextures = CVarStreamingFullyLoadUsedTextures.GetValueOnAnyThread() != 0;
	bFullyLoadMeshes = CVarStreamingFullyLoadMeshes.GetValueOnAnyThread() != 0;
	bUseAllMips = CVarStreamingUseAllMips.GetValueOnAnyThread() != 0;
	MinMipForSplitRequest = CVarStreamingMinMipForSplitRequest.GetValueOnAnyThread();
	PerTextureBiasViewBoostThreshold = CVarStreamingPerTextureBiasViewBoostThreshold.GetValueOnAnyThread();