r.Nanite.ShowStats

r.Nanite.ShowStats

#Overview

name: r.Nanite.ShowStats

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

It is referenced in 21 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.Nanite.ShowStats is to control the display of statistics for Unreal Engine 5’s Nanite virtualized geometry system. This setting variable is primarily used for debugging and performance analysis of the Nanite rendering system.

The Nanite subsystem within the Unreal Engine 5 renderer relies on this setting variable. It is referenced in various parts of the rendering code, particularly in the Nanite-specific files and the deferred shading renderer.

The value of this variable is set through the console variable system, as seen in the FAutoConsoleVariableRef declaration. It can be changed at runtime using console commands.

This variable interacts closely with GNaniteShowStats, which is the actual integer variable that stores the state. They share the same value, with r.Nanite.ShowStats being the console-accessible name and GNaniteShowStats being the C++ variable used in the code.

Developers should be aware that enabling this variable may have performance implications, as it involves additional computation and memory usage to gather and display statistics. It should primarily be used for debugging and performance analysis, not in shipping builds.

Best practices when using this variable include:

  1. Only enable it when needed for debugging or performance analysis.
  2. Be aware of the potential performance impact when enabled.
  3. Use in conjunction with other Nanite debugging tools and variables for a comprehensive view of the system’s performance.

Regarding the associated variable GNaniteShowStats:

The purpose of GNaniteShowStats is to serve as the internal C++ representation of the r.Nanite.ShowStats console variable. It is used throughout the Nanite rendering code to determine whether statistics should be gathered and displayed.

This variable is used in various Nanite-related systems, including the main Nanite rendering, culling, rasterization, and shadow rendering code.

The value of GNaniteShowStats is set by the console variable system when r.Nanite.ShowStats is modified.

GNaniteShowStats interacts with several other variables and systems within the Nanite rendering pipeline. It’s often used in conditional statements to determine whether certain statistics-related code should be executed.

Developers should be aware that this variable is used extensively throughout the Nanite rendering code, and changing its value will have wide-ranging effects on the statistics gathering and display systems.

Best practices for using GNaniteShowStats include:

  1. Avoid modifying it directly in C++ code; instead, use the r.Nanite.ShowStats console variable to change its value.
  2. When adding new Nanite-related features, consider whether they should respect this variable for statistics gathering.
  3. Be mindful of the performance implications when this variable is non-zero, especially 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/Renderer/Private/Nanite/Nanite.cpp:16

Scope: file

Source code excerpt:

int32 GNaniteShowStats = 0;
FAutoConsoleVariableRef CVarNaniteShowStats(
	TEXT("r.Nanite.ShowStats"),
	GNaniteShowStats,
	TEXT("")
);

FString GNaniteStatsFilter;
FAutoConsoleVariableRef CVarNaniteStatsFilter(

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:106

Scope: file

Source code excerpt:

#endif

extern int32 GNaniteShowStats;
extern int32 GNanitePickingDomain;

extern DynamicRenderScaling::FBudget GDynamicNaniteScalingPrimary;

static TAutoConsoleVariable<int32> CVarClearCoatNormal(
	TEXT("r.ClearCoatNormal"),

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:2440

Scope (from outer to inner):

file
function     void FDeferredShadingSceneRenderer::Render

Source code excerpt:

			if (bNaniteEnabled)
			{
				if (GNaniteShowStats != 0)
				{
					for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
					{
						const FViewInfo& View = Views[ViewIndex];
						if (IStereoRendering::IsAPrimaryView(View))
						{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:14

Scope: file

Source code excerpt:

#define NUM_PRINT_STATS_PASSES 5

int32 GNaniteShowStats = 0;
FAutoConsoleVariableRef CVarNaniteShowStats(
	TEXT("r.Nanite.ShowStats"),
	GNaniteShowStats,
	TEXT("")
);

FString GNaniteStatsFilter;
FAutoConsoleVariableRef CVarNaniteStatsFilter(
	TEXT("r.Nanite.StatsFilter"),

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:42

Scope (from outer to inner):

file
function     void NaniteStatsFilterExec

Source code excerpt:


	// Convenience, force on Nanite debug/stats and also shader printing.
	GNaniteShowStats = 1;
	ShaderPrint::SetEnabled(true);

	// parse parameters
	for (;;)
	{
		FString Parameter = FParse::Token(Cmd, 0);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:70

Scope (from outer to inner):

file
function     void NaniteStatsFilterExec

Source code excerpt:

		{
			// disable stats
			GNaniteShowStats = 0;
			return;
		}
		else
		{
			GNaniteStatsFilter = Parameter;
		}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:285

Scope (from outer to inner):

file
namespace    Nanite
function     bool IsStatFilterActive

Source code excerpt:

bool IsStatFilterActive(const FString& FilterName)
{
	if (GNaniteShowStats == 0)
	{
		// Stats are disabled, do nothing.
		return false;
	}

	return (GNaniteStatsFilter == FilterName);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:296

Scope (from outer to inner):

file
namespace    Nanite
function     bool IsStatFilterActiveForLight

Source code excerpt:

bool IsStatFilterActiveForLight(const FLightSceneProxy* LightProxy)
{
	if (GNaniteShowStats == 0)
	{
		return false;
	}

	const FString LightFilterName = Nanite::GetFilterNameForLight(LightProxy);
	return IsStatFilterActive(LightFilterName);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:405

Scope (from outer to inner):

file
namespace    Nanite
function     void ExtractShadingDebug

Source code excerpt:

	}

	if (GNaniteShowStats != 0 && Nanite::GGlobalResources.GetStatsBufferRef())
	{
		const bool bShadeBinning = ShadeBinning.ShadingBinArgs != nullptr;
		FCalculateShadingStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FCalculateShadingStatsCS::FParameters>();

		PassParameters->RenderFlags = Nanite::GGlobalResources.StatsRenderFlags;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/Nanite.cpp:450

Scope (from outer to inner):

file
namespace    Nanite
function     void PrintStats

Source code excerpt:


	// Print stats
	if (GNaniteShowStats != 0 && Nanite::GGlobalResources.GetStatsBufferRef())
	{
		auto& MainPassBuffers = Nanite::GGlobalResources.GetMainPassBuffers();
		auto& PostPassBuffers = Nanite::GGlobalResources.GetPostPassBuffers();

		// Shader compilers have a hard time handling the size of the full PrintStats shader, so we split it into multiple passes.
		// This reduces the FXC compilation time from 2-3 minutes to just a few seconds.

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:317

Scope: file

Source code excerpt:

DynamicRenderScaling::FBudget GDynamicNaniteScalingShadow( TEXT("DynamicNaniteScalingShadow"),  &GetDynamicNaniteScalingShadowSettings);

extern int32 GNaniteShowStats;
extern int32 GSkipDrawOnPSOPrecaching;

// Set to 1 to pretend all programmable raster draws are not precached yet
TAutoConsoleVariable<int32> CVarNaniteTestPrecacheDrawSkipping(
	TEXT("r.Nanite.TestPrecacheDrawSkipping"),
	0,

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:2924

Scope (from outer to inner):

file
namespace    Nanite
function     FRenderer::FRenderer

Source code excerpt:

	RenderFlags |= Configuration.bEditorShowFlag		? NANITE_RENDER_FLAG_EDITOR_SHOW_FLAG_ENABLED : 0u;
#endif
	RenderFlags |= GNaniteShowStats != 0				? NANITE_RENDER_FLAG_WRITE_STATS : 0u;

	if (UseMeshShader(ShaderPlatform, SharedContext.Pipeline))
	{
		RenderFlags |= NANITE_RENDER_FLAG_MESH_SHADER;
	}
	else if (UsePrimitiveShader())

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:4622

Scope (from outer to inner):

file
namespace    Nanite

Source code excerpt:

		PassParameters->VisiblePatchesSize			= VisiblePatches->GetSize() / 16;

		PassParameters->OutStatsBuffer				= GNaniteShowStats != 0u ? GraphBuilder.CreateUAV(StatsBuffer) : nullptr;

		if (VirtualShadowMapArray)
		{
			PassParameters->VirtualShadowMap		= VirtualTargetParameters;
		}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteCullRaster.cpp:4634

Scope (from outer to inner):

file
namespace    Nanite

Source code excerpt:

		PermutationVector.Set< FPatchSplitCS::FVirtualTextureTargetDim >( VirtualShadowMapArray != nullptr );
		PermutationVector.Set< FPatchSplitCS::FSplineDeformDim >( NaniteSplineMeshesSupported() );
		PermutationVector.Set< FPatchSplitCS::FWriteStatsDim >(GNaniteShowStats != 0u);
		
		auto ComputeShader = SharedContext.ShaderMap->GetShader< FPatchSplitCS >( PermutationVector );
		ClearUnusedGraphResources(ComputeShader, PassParameters);

		GraphBuilder.AddPass(
			RDG_EVENT_NAME("PatchSplit"),

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteMaterials.cpp:40

Scope: file

Source code excerpt:

	);

extern int32 GNaniteShowStats;

static bool UseLegacyCulling()
{
	return !UseNaniteComputeMaterials();
}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteShading.cpp:25

Scope: file

Source code excerpt:


extern int32 GSkipDrawOnPSOPrecaching;
extern int32 GNaniteShowStats;

#if WANTS_DRAW_MESH_EVENTS
static FORCEINLINE const TCHAR* GetShadingMaterialName(const FMaterialRenderProxy* InShadingMaterial)
{
	if (InShadingMaterial == nullptr)
	{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteShading.cpp:1469

Scope (from outer to inner):

file
function     FShadeBinning ShadeBinning

Source code excerpt:

	const uint32 ShadingBinCountPow2 = FMath::RoundUpToPowerOfTwo(ShadingBinCount);

	const bool bGatherStats = GNaniteShowStats != 0;

	const FUintVector4 ViewRect = FUintVector4(uint32(InViewRect.Min.X), uint32(InViewRect.Min.Y), uint32(InViewRect.Max.X), uint32(InViewRect.Max.Y));

	const uint32 PixelCount = InViewRect.Width() * InViewRect.Height();

	const int32 QuadWidth = FMath::DivideAndRoundUp(InViewRect.Width(), 2);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowDepthRendering.cpp:138

Scope: file

Source code excerpt:

	ECVF_RenderThreadSafe);

extern int32 GNaniteShowStats;
extern int32 GEnableNonNaniteVSM;

namespace Nanite
{
	extern bool IsStatFilterActive(const FString& FilterName);
	extern bool IsStatFilterActiveForLight(const FLightSceneProxy* LightProxy);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowDepthRendering.cpp:1494

Scope (from outer to inner):

file
function     static void RenderShadowDepthAtlasNanite
lambda-function

Source code excerpt:

			CullingConfig.SetViewFlags(SceneView);
	
			if (GNaniteShowStats != 0)
			{
				FString AtlasFilterName = FString::Printf(TEXT("ShadowAtlas%d"), AtlasIndex);
				CullingConfig.bExtractStats = Nanite::IsStatFilterActive(AtlasFilterName);
			}
	
			Nanite::FRasterContext RasterContext = Nanite::InitRasterContext(GraphBuilder, SharedContext, ViewFamily, AtlasSize, FullAtlasViewRect, Nanite::EOutputBufferMode::DepthOnly);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowDepthRendering.cpp:1785

Scope (from outer to inner):

file
function     void FSceneRenderer::RenderShadowDepthMaps

Source code excerpt:


				FString CubeFilterName;
				if (GNaniteShowStats != 0)
				{
					// Get the base light filter name.
					CubeFilterName = Nanite::GetFilterNameForLight(LightSceneInfo.Proxy);
					CubeFilterName.Append(TEXT("_Face_"));
				}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/ShadowDepthRendering.cpp:1833

Scope (from outer to inner):

file
function     void FSceneRenderer::RenderShadowDepthMaps

Source code excerpt:


					FString CubeFaceFilterName;
					if (GNaniteShowStats != 0)
					{
						CubeFaceFilterName = CubeFilterName;
						CubeFaceFilterName.AppendInt(CubemapFaceIndex);

						CullingConfig.bExtractStats = Nanite::IsStatFilterActive(CubeFaceFilterName);
					}