PrimitiveProbablyVisibleTime

PrimitiveProbablyVisibleTime

#Overview

name: PrimitiveProbablyVisibleTime

The value of this variable can be defined or overridden in .ini config files. 1 .ini config file referencing this setting variable.

It is referenced in 8 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of PrimitiveProbablyVisibleTime is to define a time threshold for considering primitives as probably visible after they were last actually visible in the rendering system. This setting is used to optimize occlusion culling and visibility determination in Unreal Engine 5.

PrimitiveProbablyVisibleTime is primarily used by the Renderer module, specifically in the occlusion and visibility systems. It’s referenced in SceneOcclusion.cpp and SceneVisibility.cpp, which are core components of Unreal Engine’s rendering pipeline.

The value of this variable is set in the Engine configuration, as indicated by the UPROPERTY(config) decorator in the UEngine class definition.

PrimitiveProbablyVisibleTime interacts with other time-related variables, such as LastProvenVisibleTime and CurrentRealTime, to determine whether a primitive should be considered visible or if it needs to be tested for occlusion.

Developers should be aware that this variable directly affects the performance and visual accuracy of the rendering system. A higher value will keep primitives considered visible for longer, potentially reducing the number of occlusion tests but possibly showing objects that should be occluded. A lower value will lead to more frequent occlusion testing but may provide more accurate results.

Best practices when using this variable include:

  1. Carefully tuning the value based on the specific needs of the game or application.
  2. Considering the trade-off between performance and visual accuracy.
  3. Testing thoroughly with different scenes and camera movements to ensure optimal settings.
  4. Being mindful of how changes to this variable might affect other parts of the rendering pipeline, such as occlusion query allocation and trimming of occlusion history.

#Setting Variables

#References In INI files

Location: <Workspace>/Engine/Config/BaseEngine.ini:286, section: [/Script/Engine.Engine]

#References in C++ code

#Callsites

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

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

Scope (from outer to inner):

file
class        class UEngine : public UObject , public FExec

Source code excerpt:

	/** The amount of time a primitive is considered to be probably visible after it was last actually visible. */
	UPROPERTY(config)
	float PrimitiveProbablyVisibleTime;

	/** Max screen pixel fraction where retesting when unoccluded is worth the GPU time. */
	UPROPERTY(config)
	float MaxOcclusionPixelsFraction;

	/** Whether to pause the game if focus is lost. */

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneOcclusion.cpp:1060

Scope (from outer to inner):

file
function     static void TrimAllOcclusionHistory

Source code excerpt:

		{
			const double RealTimeSeconds = View.Family->Time.GetRealTimeSeconds();
			View.ViewState->TrimOcclusionHistory(RealTimeSeconds, RealTimeSeconds - GEngine->PrimitiveProbablyVisibleTime, RealTimeSeconds, View.ViewState->OcclusionFrameCounter);
		}
	}
}

static void AllocateOcclusionTests(FViewOcclusionQueriesPerView& QueriesPerView, const FScene* Scene, TArrayView<const FVisibleLightInfo> VisibleLightInfos, TArrayView<FViewInfo> Views)
{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneOcclusion.cpp:1091

Scope (from outer to inner):

file
function     static void AllocateOcclusionTests

Source code excerpt:


			// Clear primitives which haven't been visible recently out of the occlusion history, and reset old pending occlusion queries.
			ViewState->TrimOcclusionHistory(ViewFamily.Time.GetRealTimeSeconds(), ViewFamily.Time.GetRealTimeSeconds() - GEngine->PrimitiveProbablyVisibleTime, ViewFamily.Time.GetRealTimeSeconds(), ViewState->OcclusionFrameCounter);

			// Give back all these occlusion queries to the pool.
			ShadowOcclusionQueryMap.Reset();

			if (FeatureLevel > ERHIFeatureLevel::ES3_1)
			{

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:2443

Scope (from outer to inner):

file
function     FGPUOcclusionPacket::FGPUOcclusionPacket

Source code excerpt:

	, ViewOrigin(View.ViewMatrices.GetViewOrigin())
	, OcclusionFrameCounter(ViewState.OcclusionFrameCounter)
	, PrimitiveProbablyVisibleTime(GEngine->PrimitiveProbablyVisibleTime)
	, CurrentRealTime(View.Family->Time.GetRealTimeSeconds())
	, NeverOcclusionTestDistanceSquared(GNeverOcclusionTestDistance* GNeverOcclusionTestDistance)
	, bUseOcclusionFeedback(OcclusionFeedback.IsInitialized())
	, bNewlyConsideredBBoxExpandActive(GExpandNewlyOcclusionTestedBBoxesAmount > 0.0f && GFramesToExpandNewlyOcclusionTestedBBoxes > 0 && GFramesNotOcclusionTestedToExpandBBoxes > 0)
{}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:2574

Scope: file

Source code excerpt:

						{
							// If there's no occlusion query for the primitive, set it's visibility state to whether it has been unoccluded recently.
							bIsOccluded = (PrimitiveOcclusionHistory->LastProvenVisibleTime + GEngine->PrimitiveProbablyVisibleTime < CurrentRealTime);
							// the state was definite last frame, otherwise we would have ran a query
							bOcclusionStateIsDefinite = true;
						}
						if (bIsOccluded)
						{
							PrimitiveOcclusionHistory->LastPixelsPercentage = 0.0f;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:2679

Scope: file

Source code excerpt:

							else
							{
								bRunQuery = CurrentRealTime - PrimitiveOcclusionHistory->LastProvenVisibleTime > PrimitiveProbablyVisibleTime * (0.5f * 0.25f * Rnd);
							}
						}
						else
						{
							bGroupedQuery = false;
							bRunQuery = true;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibility.cpp:5101

Scope (from outer to inner):

file
function     void FSceneRenderer::PrepareViewStateForVisibility

Source code excerpt:

			// detect conditions where we should reset occlusion queries
			if (bFirstFrameOrTimeWasReset || 
				ViewState->LastRenderTime + GEngine->PrimitiveProbablyVisibleTime < View.Family->Time.GetRealTimeSeconds() ||
				View.bCameraCut ||
				View.bForceCameraVisibilityReset ||
				IsLargeCameraMovement(
					View, 
				    FMatrix(ViewState->PrevViewMatrixForOcclusionQuery), 
				    ViewState->PrevViewOriginForOcclusionQuery, 

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneVisibilityPrivate.h:1079

Scope (from outer to inner):

file
class        class FGPUOcclusionPacket

Source code excerpt:

	const FVector ViewOrigin;
	const uint32 OcclusionFrameCounter;
	const float PrimitiveProbablyVisibleTime;
	const float CurrentRealTime;
	const float NeverOcclusionTestDistanceSquared;
	const bool bUseOcclusionFeedback;
	const bool bNewlyConsideredBBoxExpandActive;
};