r.AOGlobalDistanceFieldCacheMostlyStaticSeparately

r.AOGlobalDistanceFieldCacheMostlyStaticSeparately

#Overview

name: r.AOGlobalDistanceFieldCacheMostlyStaticSeparately

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

It is referenced in 19 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.AOGlobalDistanceFieldCacheMostlyStaticSeparately is to control whether mostly static primitives are cached separately from movable primitives in the global distance field system. This setting is primarily used in the rendering system, specifically for ambient occlusion (AO) and global distance field calculations.

This variable is mainly used in the Renderer module of Unreal Engine, particularly in the global distance field subsystem. It affects how the engine manages and updates the global distance field, which is used for various rendering effects like ambient occlusion.

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

The associated variable GAOGlobalDistanceFieldCacheMostlyStaticSeparately directly interacts with it, sharing the same value. This internal variable is used throughout the code to check the setting’s state.

Developers should be aware that:

  1. Enabling this setting (value = 1) can reduce the update cost of the global distance field when movable primitives are modified.
  2. It adds an additional 12MB of volume textures to the memory footprint.
  3. It affects various parts of the global distance field system, including page table allocation, clipmap updates, and primitive processing.

Best practices when using this variable include:

  1. Consider the trade-off between performance improvement and increased memory usage.
  2. Test the impact on your specific scene, as the benefits may vary depending on the number and nature of static vs. movable objects.
  3. Be aware that changing this setting may require adjustments to other related rendering settings for optimal performance.

Regarding the associated variable GAOGlobalDistanceFieldCacheMostlyStaticSeparately:

The purpose of GAOGlobalDistanceFieldCacheMostlyStaticSeparately is to serve as an internal representation of the r.AOGlobalDistanceFieldCacheMostlyStaticSeparately console variable. It’s used throughout the rendering code to check whether the separate caching of mostly static primitives is enabled.

This variable is used extensively in the Renderer module, specifically in the global distance field system implementation.

Its value is set by the console variable system when r.AOGlobalDistanceFieldCacheMostlyStaticSeparately is modified.

It directly interacts with various parts of the global distance field system, affecting how primitives are processed, how clipmaps are updated, and how page tables are allocated and accessed.

Developers should be aware that this variable’s state can significantly impact the behavior and performance of the global distance field system. Changes to its value will affect memory usage and update patterns of the global distance field.

Best practices include ensuring consistency between this variable and the console variable, and considering its state when optimizing or debugging global distance field-related rendering issues.

#References in C++ code

#Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:63

Scope: file

Source code excerpt:

int32 GAOGlobalDistanceFieldCacheMostlyStaticSeparately = 1;
FAutoConsoleVariableRef CVarAOGlobalDistanceFieldCacheMostlyStaticSeparately(
	TEXT("r.AOGlobalDistanceFieldCacheMostlyStaticSeparately"),
	GAOGlobalDistanceFieldCacheMostlyStaticSeparately,
	TEXT("Whether to cache mostly static primitives separately from movable primitives, which reduces global DF update cost when a movable primitive is modified.  Adds another 12Mb of volume textures."),
	ECVF_Scalability | ECVF_RenderThreadSafe
	);

int32 GAOGlobalDistanceFieldPartialUpdates = 1;

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:61

Scope: file

Source code excerpt:

	);

int32 GAOGlobalDistanceFieldCacheMostlyStaticSeparately = 1;
FAutoConsoleVariableRef CVarAOGlobalDistanceFieldCacheMostlyStaticSeparately(
	TEXT("r.AOGlobalDistanceFieldCacheMostlyStaticSeparately"),
	GAOGlobalDistanceFieldCacheMostlyStaticSeparately,
	TEXT("Whether to cache mostly static primitives separately from movable primitives, which reduces global DF update cost when a movable primitive is modified.  Adds another 12Mb of volume textures."),
	ECVF_Scalability | ECVF_RenderThreadSafe
	);

int32 GAOGlobalDistanceFieldPartialUpdates = 1;
FAutoConsoleVariableRef CVarAOGlobalDistanceFieldPartialUpdates(

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:475

Scope (from outer to inner):

file
function     FIntVector GlobalDistanceField::GetPageAtlasSizeInPages

Source code excerpt:

	const int32 RequiredNumberOfPages = FMath::CeilToInt(
		PageTableTextureResolution.X * PageTableTextureResolution.Y * PageTableTextureResolution.Z 
		* (GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? 2 : 1)
		* FMath::Clamp(GGlobalDistanceFieldOccupancyRatio, 0.1f, 1.0f));

	const int32 RequiredNumberOfPagesInZ = FMath::DivideAndRoundUp(RequiredNumberOfPages, GlobalDistanceField::PageAtlasSizeInPagesX * GlobalDistanceField::PageAtlasSizeInPagesY);

	const FIntVector PageAtlasTextureSizeInPages = FIntVector(
		GlobalDistanceField::PageAtlasSizeInPagesX,

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:556

Scope (from outer to inner):

file
function     void FGlobalDistanceFieldInfo::UpdateParameterData

Source code excerpt:

		if (PageTableCombinedTexture)
		{
			ensureMsgf(GAOGlobalDistanceFieldCacheMostlyStaticSeparately, TEXT("PageTableCombinedTexture should only be allocated when caching mostly static objects separately."));
			ParameterData.PageTableTexture = PageTableCombinedTexture->GetRHI();
		}
		else if (PageTableLayerTextures[GDF_Full])
		{
			ensureMsgf(!GAOGlobalDistanceFieldCacheMostlyStaticSeparately, TEXT("PageTableCombinedTexture should be allocated when caching mostly static objects separately."));
			ParameterData.PageTableTexture = PageTableLayerTextures[GDF_Full]->GetRHI();
		}

		FIntVector MipTextureResolution(1, 1, 1);
		if (MipTexture)
		{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:922

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

		}

		if(GAOGlobalDistanceFieldCacheMostlyStaticSeparately)
		{
			const FIntVector PageTableTextureResolution = GlobalDistanceField::GetPageTableTextureResolution(bLumenEnabled, View.FinalPostProcessSettings.LumenSceneViewDistance);
			TRefCountPtr<IPooledRenderTarget>& PageTableTexture = GlobalDistanceFieldData.PageTableCombinedTexture;

			if (!PageTableTexture
					|| PageTableTexture->GetDesc().Extent.X != PageTableTextureResolution.X

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:993

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

			TRefCountPtr<IPooledRenderTarget>& PageTableTexture = GlobalDistanceFieldData.PageTableLayerTextures[CacheType];

			if (CacheType == GDF_Full || GAOGlobalDistanceFieldCacheMostlyStaticSeparately)
			{
				if (!PageTableTexture
					|| PageTableTexture->GetDesc().Extent.X != PageTableTextureResolution.X
					|| PageTableTexture->GetDesc().Extent.Y != PageTableTextureResolution.Y
					|| PageTableTexture->GetDesc().Depth != PageTableTextureResolution.Z)
				{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1078

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

			for (uint32 CacheType = 0; CacheType < GDF_Num; CacheType++)
			{
				const uint32 DestCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? CacheType : GDF_Full;
				ClipmapViewState.Cache[DestCacheType].PrimitiveModifiedBounds.Append(Scene->DistanceFieldSceneData.PrimitiveModifiedBounds[CacheType]);
			}

			const bool bForceFullUpdate = bSharedDataReallocated
				|| bForceFullUpdateMGPU
				|| !GlobalDistanceFieldData.bInitializedOrigins
				// Detect when max occlusion distance has changed
				|| ClipmapViewState.CachedClipmapExtent != ClipmapExtent
				|| ClipmapViewState.CacheMostlyStaticSeparately != GAOGlobalDistanceFieldCacheMostlyStaticSeparately
				|| ClipmapViewState.LastUsedSceneDataForFullUpdate != &Scene->DistanceFieldSceneData
				|| GAOGlobalDistanceFieldForceFullUpdate
				|| GAOGlobalDistanceFieldForceUpdateOnce
				|| GDFReadbackRequest != nullptr;

			const bool bUpdateRequested = GAOUpdateGlobalDistanceField != 0 && ShouldUpdateClipmapThisFrame(ClipmapIndex, NumClipmaps, GlobalDistanceFieldData.UpdateIndex);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1124

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

				}

				const FGlobalDFCacheType StartCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GDF_MostlyStatic : GDF_Full;

				for (uint32 CacheType = StartCacheType; CacheType < GDF_Num; CacheType++)
				{
					FGlobalDistanceFieldClipmap& Clipmap = *(CacheType == GDF_MostlyStatic
						? &GlobalDistanceFieldInfo.MostlyStaticClipmaps[ClipmapIndex]
						: &GlobalDistanceFieldInfo.Clipmaps[ClipmapIndex]);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1171

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

						}

						if (CacheType == GDF_MostlyStatic || !GAOGlobalDistanceFieldCacheMostlyStaticSeparately)
						{
							// Add an update region for each potential axis of camera movement
							AddUpdateBoundsForAxis(MovementInPages, ClipmapBounds, ClipmapPageSize, 0, Clipmap.UpdateBounds);
							AddUpdateBoundsForAxis(MovementInPages, ClipmapBounds, ClipmapPageSize, 1, Clipmap.UpdateBounds);
							AddUpdateBoundsForAxis(MovementInPages, ClipmapBounds, ClipmapPageSize, 2, Clipmap.UpdateBounds);
						}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1236

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:


			const FVector SnappedCenter = FVector(ClipmapViewState.LastPartialUpdateOriginInPages) * ClipmapPageSize;
			const FGlobalDFCacheType StartCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GDF_MostlyStatic : GDF_Full;

			for (uint32 CacheType = StartCacheType; CacheType < GDF_Num; CacheType++)
			{
				FGlobalDistanceFieldClipmap& Clipmap = *(CacheType == GDF_MostlyStatic 
					? &GlobalDistanceFieldInfo.MostlyStaticClipmaps[ClipmapIndex] 
					: &GlobalDistanceFieldInfo.Clipmaps[ClipmapIndex]);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1256

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

			ClipmapViewState.CachedClipmapExtent = ClipmapExtent;
			ClipmapViewState.CacheClipmapInfluenceRadius = ClipmapInfluenceRadius;
			ClipmapViewState.CacheMostlyStaticSeparately = GAOGlobalDistanceFieldCacheMostlyStaticSeparately;
		}
		GAOGlobalDistanceFieldForceUpdateOnce = 0;

		ensureMsgf(!GAOGlobalDistanceFieldStaggeredUpdates || NumClipmapUpdateRequests <= GetNumClipmapUpdatesPerFrame(), TEXT("ShouldUpdateClipmapThisFrame needs to be adjusted for the NumClipmaps to even out the work distribution"));
	}
	else

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:1266

Scope (from outer to inner):

file
function     static void ComputeUpdateRegionsAndUpdateViewState

Source code excerpt:

		for (int32 ClipmapIndex = 0; ClipmapIndex < NumClipmaps; ClipmapIndex++)
		{
			const FGlobalDFCacheType StartCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GDF_MostlyStatic : GDF_Full;

			for (uint32 CacheType = StartCacheType; CacheType < GDF_Num; CacheType++)
			{
				FGlobalDistanceFieldClipmap& Clipmap = *(CacheType == GDF_MostlyStatic
					? &GlobalDistanceFieldInfo.MostlyStaticClipmaps[ClipmapIndex]
					: &GlobalDistanceFieldInfo.Clipmaps[ClipmapIndex]);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:2267

Scope: file

Source code excerpt:


		const int32 NumHeightfieldPrimitives = DistanceFieldSceneData.HeightfieldPrimitives.Num();
		if ((CacheType == GDF_MostlyStatic || !GAOGlobalDistanceFieldCacheMostlyStaticSeparately)
			&& NumHeightfieldPrimitives > 0
			&& GAOGlobalDistanceFieldRepresentHeightfields
			&& !IsVulkanMobileSM5Platform(Scene->GetShaderPlatform()))
		{
			for (int32 HeightfieldPrimitiveIndex = 0; HeightfieldPrimitiveIndex < NumHeightfieldPrimitives; HeightfieldPrimitiveIndex++)
			{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:2411

Scope (from outer to inner):

file
function     BEGIN_SHADER_PARAMETER_STRUCT

Source code excerpt:

			uint32 AcceptOftenMovingObjectsOnlyValue = 0;

			if (!GAOGlobalDistanceFieldCacheMostlyStaticSeparately)
			{
				AcceptOftenMovingObjectsOnlyValue = 2;
			}
			else if (CacheType == GDF_Full)
			{
				// First cache is for mostly static, second contains both, inheriting static objects distance fields with a lookup

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:3072

Scope: file

Source code excerpt:

				FPropagateMipDistanceCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FPropagateMipDistanceCS::FParameters>();
				PassParameters->RWMipTexture = NextTextureUAV;
				PassParameters->PageTableTexture = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? PageTableCombinedTexture : PageTableLayerTexture;
				PassParameters->PageAtlasTexture = PageAtlasTexture;
				PassParameters->DistanceFieldSampler = TStaticSamplerState<SF_Bilinear, AM_Wrap, AM_Wrap, AM_Wrap>::GetRHI();
				PassParameters->GlobalDistanceFieldInvPageAtlasSize = FVector3f::OneVector / FVector3f(GlobalDistanceField::GetPageAtlasSize(bLumenEnabled, View.FinalPostProcessSettings.LumenSceneViewDistance));
				PassParameters->GlobalDistanceFieldClipmapSizeInPages = GlobalDistanceField::GetPageTableTextureResolution(bLumenEnabled, View.FinalPostProcessSettings.LumenSceneViewDistance).X;
				PassParameters->PrevMipTexture = PrevTexture;
				PassParameters->ClipmapMipResolution = ClipmapMipResolution;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:3158

Scope (from outer to inner):

file
function     void UpdateGlobalDistanceFieldVolume

Source code excerpt:


			bNeedsFinalizeAccess = false;
			const FGlobalDFCacheType StartCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GDF_MostlyStatic : GDF_Full;
			FGlobalDistanceFieldInfoRDG GlobalDistanceFieldInfoRDG;

			RegisterGlobalDistanceFieldExternalResources(GraphBuilder, GlobalDistanceFieldInfo, StartCacheType, GlobalDistanceFieldInfoRDG);

			FRDGBufferRef PageFreeListAllocatorBuffer = GlobalDistanceFieldInfoRDG.PageFreeListAllocatorBuffer;
			FRDGBufferRef PageFreeListBuffer = GlobalDistanceFieldInfoRDG.PageFreeListBuffer;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:3220

Scope (from outer to inner):

file
function     void UpdateGlobalDistanceFieldVolume

Source code excerpt:

				FRDGTextureRef ParentPageTableLayerTexture = nullptr;

				if (CacheType == GDF_Full && GAOGlobalDistanceFieldCacheMostlyStaticSeparately && PageTableLayerTextures[GDF_MostlyStatic])
				{
					ParentPageTableLayerTexture = PageTableLayerTextures[GDF_MostlyStatic];
				}

				TArray<FGlobalDistanceFieldClipmap>& Clipmaps = CacheType == GDF_MostlyStatic
					? GlobalDistanceFieldInfo.MostlyStaticClipmaps

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:3259

Scope (from outer to inner):

file
function     void UpdateGlobalDistanceFieldVolume

Source code excerpt:

			ShaderPrint::SetEnabled(true);

			FRDGTextureRef PageTableCombinedTexture = GraphBuilder.RegisterExternalTexture(GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GlobalDistanceFieldInfo.PageTableCombinedTexture : GlobalDistanceFieldInfo.PageTableLayerTextures[0], TEXT("GlobalDistanceField.PageTableCombined"));
			FRDGTextureRef PageAtlasTexture = GraphBuilder.RegisterExternalTexture(GlobalDistanceFieldInfo.PageAtlasTexture, TEXT("GlobalDistanceField.PageAtlasTexture"));

			for (int32 ClipmapIndex = 0; ClipmapIndex < GlobalDistanceFieldInfo.ParameterData.NumGlobalSDFClipmaps; ClipmapIndex++)
			{
				FGlobalDistanceFieldPageStatsCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FGlobalDistanceFieldPageStatsCS::FParameters>();
				PassParameters->RWPageStatsBuffer = GraphBuilder.CreateUAV(PageStatsBuffer);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/GlobalDistanceField.cpp:3310

Scope (from outer to inner):

file
function     void UpdateGlobalDistanceFieldVolume

Source code excerpt:

	if (bNeedsFinalizeAccess)
	{
		const FGlobalDFCacheType StartCacheType = GAOGlobalDistanceFieldCacheMostlyStaticSeparately ? GDF_MostlyStatic : GDF_Full;
		FGlobalDistanceFieldInfoRDG GlobalDistanceFieldInfoRDG;

		RegisterGlobalDistanceFieldExternalResources(GraphBuilder, GlobalDistanceFieldInfo, StartCacheType, GlobalDistanceFieldInfoRDG);
		FinalizeGlobalDistanceFieldExternalResourceAccess(GraphBuilder, ExternalAccessQueue, GlobalDistanceFieldInfo, StartCacheType, GlobalDistanceFieldInfoRDG);
	}
#endif