r.FastVRam.Histogram

r.FastVRam.Histogram

#Overview

name: r.FastVRam.Histogram

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

It is referenced in 28 C++ source files.

#Summary

#Usage in the C++ source code

The purpose of r.FastVRam.Histogram is to control the texture creation flags for the histogram texture used in the rendering pipeline, specifically for post-processing effects related to eye adaptation and HDR (High Dynamic Range) rendering.

This setting variable is primarily used by the rendering system in Unreal Engine 5. It affects how the histogram texture is allocated in memory, potentially improving performance on certain hardware by utilizing fast VRAM.

The value of this variable is set through a console variable (CVar) system, which allows it to be modified at runtime or through configuration files. It is initialized in the engine’s startup process and can be updated during runtime.

The r.FastVRam.Histogram variable interacts with other FastVRam settings, such as r.FastVRam.EyeAdaptation and r.FastVRam.HistogramReduce. These settings collectively control how various textures used in post-processing are allocated.

Developers should be aware that changing this variable can affect memory usage and potentially performance. It’s important to profile and test changes to ensure they provide the desired benefits without negative side effects.

Best practices when using this variable include:

  1. Only modify it if you understand the implications on memory usage and rendering performance.
  2. Test changes across different hardware configurations to ensure compatibility.
  3. Consider the relationship with other FastVRam settings to maintain consistent behavior.

The associated variable “Histogram” is used internally in the engine to store the actual texture creation flags. It’s updated based on the value of r.FastVRam.Histogram and is used when creating the histogram texture. This variable is part of the FFastVramConfig struct, which manages various FastVRam settings for different rendering components.

The purpose of the Histogram variable is to directly apply the texture creation flags when allocating the histogram texture in the rendering pipeline. It’s used in various parts of the engine, particularly in post-processing passes related to eye adaptation and HDR rendering.

Developers should be aware that modifying the Histogram variable directly is not recommended. Instead, changes should be made through the r.FastVRam.Histogram console variable, which will then update the Histogram variable through the engine’s internal mechanisms.

#References in C++ code

#Callsites

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

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

Scope: file

Source code excerpt:

FASTVRAM_CVAR(Downsample, 1);
FASTVRAM_CVAR(EyeAdaptation, 1);
FASTVRAM_CVAR(Histogram, 1);
FASTVRAM_CVAR(HistogramReduce, 1);
FASTVRAM_CVAR(VelocityFlat, 1);
FASTVRAM_CVAR(VelocityMax, 1);
FASTVRAM_CVAR(MotionBlur, 1);
FASTVRAM_CVAR(Tonemap, 1);
FASTVRAM_CVAR(Upscale, 1);

#Associated Variable and Callsites

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

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEditor/Private/STG_TextureDetails.cpp:163

Scope (from outer to inner):

file
function     void STG_TextureDetails::CalculateHistogram
lambda-function

Source code excerpt:

			return (AsyncBlobResultPtr)(cti::make_ready_continuable<const Blob*>(nullptr));
		})
		.then([this, InBlob](const Blob* Histogram) mutable
		{
			if (DoesSharedInstanceExist() && !InBlob->IsTransient())
			{
				TiledBlobPtr FinalizedHistogram = std::static_pointer_cast<TiledBlob>(InBlob->GetHistogram());
				if (HistogramBlobWidgetR.IsValid())
				{

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Data/Blob.cpp:496

Scope (from outer to inner):

file
function     BlobPtr Blob::GetHistogram

Source code excerpt:

BlobPtr	Blob::GetHistogram() const
{ 
	return Histogram ? Histogram : std::static_pointer_cast<Blob>(TextureHelper::GetBlack()); 
}

void Blob::AddLinkedBlob(BlobPtr LinkedBlob)
{
	if (IsFinalised())
	{

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Data/Blob.cpp:512

Scope (from outer to inner):

file
function     void Blob::SyncWith

Source code excerpt:

{
	/// Synchronise the histograms
	if (!Histogram && RHS->Histogram)
		Histogram = RHS->Histogram;
	else if (Histogram && !RHS->Histogram)
		RHS->Histogram = Histogram;
	else if (Histogram && RHS->Histogram)
	{
		/// Sync based on whatever has been finalised
		if (RHS->Histogram->IsFinalised() && !Histogram->IsFinalised())
			Histogram->FinaliseFrom(RHS->Histogram.get());
		else if (Histogram->IsFinalised() && !RHS->Histogram->IsFinalised())
			RHS->Histogram->FinaliseFrom(Histogram.get());

		/// If both have been finalised then there's nothing we should do.
		/// We have two copies within the system and in due course, one
		/// of these will get deleted
	}
}

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Data/Blob.h:55

Scope (from outer to inner):

file
class        class Blob : public std::enable_shared_from_this<Blob>

Source code excerpt:

	std::shared_ptr<float>			MaxValue;						/// Extracted min value (this is not always present)

	BlobPtr							Histogram;						/// The blob that's used for storing histogram data. not always have a histogram only created when required.

	BlobPtrW						LODParent;						/// The parent of this blob. Essentially the blob that was used to generate THIS lod Level
	BlobPtrW						LODSource;						/// The original source of this blob, the mip Level 0

	bool							bIsLODLevel = false;			/// Whether this blob already represents an LOD'd blob
	LinkedBlobsVec					LinkedBlobs;					/// Blobs that are linked to this tiled blob. These are objects that are 

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Data/Blob.h:183

Scope (from outer to inner):

file
class        class Blob : public std::enable_shared_from_this<Blob>
function     void SetHistogram

Source code excerpt:


	//Sets the histogram of the blob 
	FORCEINLINE void				SetHistogram(BlobPtr InHistogram) { check(!Histogram); Histogram = InHistogram; }
	//Check if blob already has a histogram
	FORCEINLINE bool				HasHistogram() const { return Histogram != nullptr; }

	//////////////////////////////////////////////////////////////////////////
	/// Static functions
	//////////////////////////////////////////////////////////////////////////

	static CHashPtr					CalculateMipHash(CHashPtr MainHash, int32 Level);

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Transform/Utility/T_TextureHistogram.h:54

Scope (from outer to inner):

file
class        class FxMaterial_Histogram : public FxMaterial_Compute<CmpSH_Type>
function     void SetBuffer

Source code excerpt:

		Buffer.Initialize(RHI, TEXT("HistogramRBuffer"), sizeof(uint32) * 4, 256, BUF_UnorderedAccess | BUF_ShaderResource);
		RHI.ClearUAVUint(Buffer.UAV, FUintVector4(0, 0, 0, 0));
		FxMaterial_Compute<CmpSH_Type>::Params.Histogram = Buffer.UAV;
	}
};

/**
 * T_TextureHistogram Transform
 */

#Loc: <Workspace>/Engine/Plugins/Experimental/TextureGraph/Source/TextureGraphEngine/Transform/Utility/T_TextureHistogram.h:73

Scope (from outer to inner):

file
class        class T_TextureHistogram

Source code excerpt:

private:
	static RenderMaterial_FXPtr CreateMaterial_Histogram(FString Name, FString OutputId, const CSH_Histogram::FPermutationDomain& cmpshPermutationDomain,int NumThreadsX, int NumThreadsY, int NumThreadsZ = 1);
	static TiledBlobPtr			CreateJobAndResult(JobUPtr& OutJob, MixUpdateCyclePtr Cycle, TiledBlobPtr Histogram, int32 TargetId);
};

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/ProfilerFPSAnalyzer.cpp:8

Scope (from outer to inner):

file
function     void FFPSAnalyzer::Reset

Source code excerpt:

{
	Samples.Reset();
	Histogram.Reset();
	Histogram.AddZeroed((MaxVal-MinVal)/Interval+1);
	MinFPS = 9999;
	MaxFPS = 0;
	AveFPS = 0;
	FPS90 = 0;
	FPS60 = 0;
	FPS30 = 0;

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/ProfilerFPSAnalyzer.cpp:27

Scope (from outer to inner):

file
function     void FFPSAnalyzer::AddSample

Source code excerpt:

	float DeltaSeconds = 1.0f / FPSSample;
	int32 Index = FPlatformMath::FloorToInt(FPSSample / (float)Interval);
	Index = Index >= Histogram.Num() ? Histogram.Num()-1 : Index;
	
	Histogram[Index].Count++;
	Histogram[Index].CummulativeTime += DeltaSeconds;
	
	if (FPSSample >= 90)
	{
		FPS90++;
	}
	

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/ProfilerFPSAnalyzer.cpp:73

Scope (from outer to inner):

file
function     SIZE_T FFPSAnalyzer::GetMemoryUsage

Source code excerpt:

SIZE_T FFPSAnalyzer::GetMemoryUsage() const
{
	const SIZE_T MemoryAllocated = Samples.GetAllocatedSize() + Histogram.GetAllocatedSize();
	return MemoryAllocated;
}


int32 FFPSAnalyzer::GetTotalCount()
{

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/ProfilerFPSAnalyzer.cpp:87

Scope (from outer to inner):

file
function     int32 FFPSAnalyzer::GetCount

Source code excerpt:

{
	int32 Index = FPlatformMath::FloorToInt(InMinVal / (float)Interval);
	Index = Index >= Histogram.Num() ? Histogram.Num()-1 : Index;

	return Histogram[Index].Count;
}

#endif // STATS

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/ProfilerFPSAnalyzer.h:67

Scope (from outer to inner):

file
class        class FFPSAnalyzer : public IHistogramDataSource

Source code excerpt:


	TArray<float> Samples;
	TArray<FProfilerFPSChartEntry> Histogram;
	float MinFPS;
	float MaxFPS;
	float AveFPS;
	int32 FPS90;
	int32 FPS60;
	int32 FPS30;

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/Widgets/SProfilerFPSChartPanel.cpp:209

Scope (from outer to inner):

file
function     BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION void SProfilerFPSChartPanel::Construct

Source code excerpt:

			.FillWidth(1.0f)
			[
				SAssignNew(Histogram, SHistogram)
				.Description(FHistogramDescription(InArgs._FPSAnalyzer.ToSharedRef(), 5, 0, 90, true))
			]

			+SHorizontalBox::Slot()
			.AutoWidth()
			[

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/Widgets/SProfilerFPSChartPanel.cpp:237

Scope (from outer to inner):

file
function     END_SLATE_FUNCTION_BUILD_OPTIMIZATION void SProfilerFPSChartPanel::ProfilerManager_OnViewModeChanged

Source code excerpt:

		const TSharedPtr<FProfilerSession> ProfilerSession = ProfilerManager->GetProfilerSession();

		Histogram->SetFPSAnalyzer(ProfilerSession->FPSAnalyzer);
		StatisticsPanel->SetFPSAnalyzer(ProfilerSession->FPSAnalyzer);
	}
}

#undef LOCTEXT_NAMESPACE

#Loc: <Workspace>/Engine/Source/Developer/Profiler/Private/Widgets/SProfilerFPSChartPanel.h:46

Scope (from outer to inner):

file
class        class SProfilerFPSChartPanel : public SCompoundWidget

Source code excerpt:


	/** The descriptions panel of the chart */
	TSharedPtr<SHistogram> Histogram;

	/** The descriptions panel of the chart */
	TSharedPtr<SProfilerFPSStatisticsPanel> StatisticsPanel;
};

#endif // STATS

#Loc: <Workspace>/Engine/Source/Developer/TraceInsights/Private/Insights/ViewModels/CounterAggregation.cpp:21

Scope (from outer to inner):

file
namespace    Insights

Source code excerpt:


	// Histogram for computing median and lower/upper quartiles.
	int32 Histogram[HistogramLen];
	Type DT; // bucket size

	TAggregatedStatsEx()
	{
		FMemory::Memzero(Histogram, sizeof(int32) * HistogramLen);
		DT = Type(1);
	}
};

////////////////////////////////////////////////////////////////////////////////////////////////////
// TCounterAggregationHelper

#Loc: <Workspace>/Engine/Source/Developer/TraceInsights/Private/Insights/ViewModels/CounterAggregation.cpp:236

Scope (from outer to inner):

file
namespace    Insights
function     void TCounterAggregationHelper<Type>::UpdateHistogram

Source code excerpt:

		Index = TAggregatedStatsEx<Type>::HistogramLen - 1;
	}
	StatsEx.Histogram[Index]++;
}

////////////////////////////////////////////////////////////////////////////////////////////////////

template<typename Type>
void TCounterAggregationHelper<Type>::PostProcess(TAggregatedStatsEx<Type>& StatsEx, bool bComputeMedian)

#Loc: <Workspace>/Engine/Source/Developer/TraceInsights/Private/Insights/ViewModels/CounterAggregation.cpp:259

Scope (from outer to inner):

file
namespace    Insights
function     void TCounterAggregationHelper<Type>::PostProcess

Source code excerpt:

			for (int32 HistogramIndex = 0; HistogramIndex < TAggregatedStatsEx<Type>::HistogramLen; HistogramIndex++)
			{
				Count += StatsEx.Histogram[HistogramIndex];
				if (Count > HalfCount)
				{
					Stats.Median = Stats.Min + HistogramIndex * StatsEx.DT;

					if (HistogramIndex > 0 &&
						StatsEx.Count % 2 == 0 &&
						Count - StatsEx.Histogram[HistogramIndex] == HalfCount)
					{
						const Type PrevMedian = Stats.Min + (HistogramIndex - 1) * StatsEx.DT;
						Stats.Median = (Stats.Median + PrevMedian) / 2;
					}

					break;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Lumen/LumenSceneRendering.cpp:463

Scope: file

Source code excerpt:

	TArray<FSurfaceCacheRequest> SurfaceCacheRequests;
	TArray<int32> CardsToHide;
	int32 Histogram[Lumen::NumDistanceBuckets] { 0 };

	void AnyThreadTask()
	{
		QUICK_SCOPE_CYCLE_COUNTER(LumenSurfaceCacheUpdateMeshCardsTask)

		const int32 LastLumenMeshCardsIndex = FMath::Min(FirstMeshCardsIndex + NumMeshCardsPerPacket, LumenMeshCards.Num());

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Lumen/LumenSceneRendering.cpp:533

Scope (from outer to inner):

file
function     void AnyThreadTask

Source code excerpt:


						const int32 DistanceBin = Lumen::GetMeshCardDistanceBin(Distance);
						Histogram[DistanceBin]++;

						ensure(Request.IsLockedMip());
					}
				}
			}
		}

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Lumen/LumenSceneRendering.cpp:1168

Scope (from outer to inner):

file
function     void UpdateSurfaceCacheMeshCards

Source code excerpt:

		for (int32 i = 0; i < Lumen::NumDistanceBuckets; ++i)
		{
			RequestHistogram[i] += Task.Histogram[i];
		}

		for (int32 CardIndex : Task.CardsToHide)
		{
			FLumenCard& Card = LumenSceneData.Cards[CardIndex];

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessHistogram.cpp:262

Scope (from outer to inner):

file
function     static FRDGTextureRef AddHistogramLegacyPass

Source code excerpt:

			PF_FloatRGBA,
			FClearValueBinding::None,
			GFastVRamConfig.Histogram | TexCreate_RenderTargetable | TexCreate_UAV | TexCreate_ShaderResource);

		HistogramTexture = GraphBuilder.CreateTexture(TextureDesc, TEXT("Histogram"));

		FHistogramCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FHistogramCS::FParameters>();
		PassParameters->View = View.ViewUniformBuffer;
		PassParameters->Input = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(SceneColor));
		PassParameters->InputSampler = TStaticSamplerState<SF_Point, AM_Clamp, AM_Clamp, AM_Clamp>::GetRHI();
		PassParameters->InputTexture = SceneColor.TextureSRV;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessHistogram.cpp:417

Scope (from outer to inner):

file
function     static FRDGTextureRef AddHistogramAtomicPass

Source code excerpt:

				TexCreate_ShaderResource | TexCreate_UAV);

			HistogramTexture = GraphBuilder.CreateTexture(TextureDescGather, TEXT("Histogram"));
		}

		FHistogramAtomicConvertCS::FParameters* PassParameters = GraphBuilder.AllocParameters<FHistogramAtomicConvertCS::FParameters>();
		PassParameters->Input = GetScreenPassTextureViewportParameters(FScreenPassTextureViewport(SceneColor));
		PassParameters->EyeAdaptationBuffer = GraphBuilder.CreateSRV(EyeAdaptationBuffer);
		// PassParameters->HistogramScatter64Texture = HistogramScatter64Texture;

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessVisualizeHDR.cpp:142

Scope (from outer to inner):

file
function     FScreenPassTexture AddVisualizeHDRPass
lambda-function

Source code excerpt:

			break;
		case EAutoExposureMethod::AEM_Histogram:
			Line = FString::Printf(TEXT("Histogram"));
			break;
		case EAutoExposureMethod::AEM_Manual:
			Line = FString::Printf(TEXT("Manual"));
			break;
		default:
			Line = FString::Printf(TEXT("Unknown"));
			break;
		}
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("Auto Exposure Method:"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

		Line = FString::Printf(TEXT("%g%% .. %g%%"), View.FinalPostProcessSettings.AutoExposureLowPercent, View.FinalPostProcessSettings.AutoExposureHighPercent);
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("Percent Low/High:"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

		if (bExtendedLuminanceRange)
		{
			Line = FString::Printf(TEXT("%.1f .. %.1f"), View.FinalPostProcessSettings.AutoExposureMinBrightness, View.FinalPostProcessSettings.AutoExposureMaxBrightness);
		}
		else
		{
			Line = FString::Printf(TEXT("%.1f .. %.1f"), LuminanceToEV100(LuminanceMax,View.FinalPostProcessSettings.AutoExposureMinBrightness), LuminanceToEV100(LuminanceMax,View.FinalPostProcessSettings.AutoExposureMaxBrightness));
		}
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("EV100 Min/Max"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(0.3f, 0.3f, 1));

		Line = FString::Printf(TEXT("%g / %g"), View.FinalPostProcessSettings.AutoExposureSpeedUp, View.FinalPostProcessSettings.AutoExposureSpeedDown);
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("Speed Up/Down:"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

		float AutoExposureBias = View.FinalPostProcessSettings.AutoExposureBias;
		{
			float AverageSceneLuminance = View.GetLastAverageSceneLuminance();

			float CurveExposureBias = 0.0f;
			float AverageSceneLuminanceEV100 = 0.0f;
			if (AverageSceneLuminance > 0)
			{
				// We need the Log2(0.18) to convert from average luminance to saturation luminance
				AverageSceneLuminanceEV100 = LuminanceToEV100(LuminanceMax, AverageSceneLuminance) + FMath::Log2(1.0f / 0.18f);
				if (View.FinalPostProcessSettings.AutoExposureBiasCurve)
				{
					CurveExposureBias = View.FinalPostProcessSettings.AutoExposureBiasCurve->GetFloatValue(AverageSceneLuminanceEV100);
				}
			}

			Line = FString::Printf(TEXT("%.3g"), AverageSceneLuminanceEV100);
			Canvas.DrawShadowedString(X, Y += YStep, TEXT("Average Scene EV100:"), GetStatsFont(), FLinearColor(1, 1, 1));
			Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

			Line = FString::Printf(TEXT("%.3g"), AutoExposureBias);
			Canvas.DrawShadowedString(X, Y += YStep, TEXT("Exposure Compensation (Settings):"), GetStatsFont(), FLinearColor(1, 1, 1));
			Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

			Line = FString::Printf(TEXT("%.3g"), CurveExposureBias);
			Canvas.DrawShadowedString(X, Y += YStep, TEXT("Exposure Compensation (Curve):"), GetStatsFont(), FLinearColor(1, 1, 1));
			Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 1, 1));

			const float ScreenCenterX = Output.ViewRect.Min.X + Output.ViewRect.Width() * 0.5f;
			const float ScreenCenterY = Output.ViewRect.Min.Y + Output.ViewRect.Height() * 0.5f;

			const float IlluminanceMeterTextX = (ScreenCenterX - 10.0f) / DPIScale;
			const float IlluminanceMeterTextY = (ScreenCenterY - 140.0f) / DPIScale;
			if(IsIlluminanceMeterSupportedByView(View))
			{
				Canvas.DrawShadowedString(IlluminanceMeterTextX, IlluminanceMeterTextY   , TEXT("Illuminance meter - over the hemisphere of the surface patch"), GetStatsFont(), FLinearColor(1, 1, 1));
				Canvas.DrawShadowedString(IlluminanceMeterTextX, IlluminanceMeterTextY+15, TEXT("                    (Forced to be a perfect white diffuse only surface)"), GetStatsFont(), FLinearColor(1, 1, 1));
			}
			else
			{
				Canvas.DrawShadowedString(IlluminanceMeterTextX, IlluminanceMeterTextY, TEXT("Illuminance meter - not available with Forward Shading"), GetStatsFont(), FLinearColor(1, 1, 1));
			}

			const float LuminanceMeterTextX = (ScreenCenterX - 10.0f) / DPIScale;
			const float LuminanceMeterTextY = (ScreenCenterY - 40.0f) / DPIScale;
			Canvas.DrawShadowedString(LuminanceMeterTextX, LuminanceMeterTextY, TEXT("Luminance meter"), GetStatsFont(), FLinearColor(1, 1, 1));

			AutoExposureBias += CurveExposureBias;
		}

		// Draw EV100 values at the bottom of the histogram
		{
			const float MinX = Output.ViewRect.Min.X + 64 + 8;
			const float MaxY = Output.ViewRect.Max.Y - 68;
			const float SizeX = Output.ViewRect.Width() - 64 * 2 - 20;

			for (uint32 i = 0; i <= 4; ++i)
			{
				int XAdd = (int)(i * SizeX / 4);
				float HistogramPosition = i / 4.0f;
				float EV100Value = FMath::Lerp(View.FinalPostProcessSettings.HistogramLogMin, View.FinalPostProcessSettings.HistogramLogMax, HistogramPosition);
				if (!bExtendedLuminanceRange)
				{
					// In this case the post process settings are actually Log2 values.
					EV100Value = Log2ToEV100(LuminanceMax, EV100Value);
				}

				Line = FString::Printf(TEXT("%.2g"), EV100Value);

				const float PosX = (MinX + XAdd - 5) / DPIScale;
				const float PosY = (MaxY + YStep) / DPIScale;

				Canvas.DrawShadowedString(PosX, PosY, *Line, GetStatsFont(), FLinearColor(1, 0.3f, 0.3f));
			}
		}

		Line = FString::Printf(TEXT("%.3g"), AutoExposureBias);
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("Exposure Compensation (All): "), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(1, 0.3f, 0.3f));

		if (bExtendedLuminanceRange)
		{
			Line = FString::Printf(TEXT("%.1f .. %.1f"), View.FinalPostProcessSettings.HistogramLogMin, View.FinalPostProcessSettings.HistogramLogMax);
		}
		else
		{
			Line = FString::Printf(TEXT("%.1f .. %.1f"), Log2ToEV100(LuminanceMax,View.FinalPostProcessSettings.HistogramLogMin), Log2ToEV100(LuminanceMax,View.FinalPostProcessSettings.HistogramLogMax));
		}

		Canvas.DrawShadowedString(X, Y += YStep, TEXT("Histogram EV100 Min/Max:"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(0.3f, 0.3f, 1));

		Line = FString::Printf(TEXT("%.5g"), View.PreExposure);
		Canvas.DrawShadowedString(X, Y += YStep, TEXT("PreExposure Value:"), GetStatsFont(), FLinearColor(1, 1, 1));
		Canvas.DrawShadowedString(X + ColumnWidth, Y, *Line, GetStatsFont(), FLinearColor(0.3f, 0.3f, 1));


	});

	return MoveTemp(Output);
}

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

Scope: file

Source code excerpt:

FASTVRAM_CVAR(Downsample, 1);
FASTVRAM_CVAR(EyeAdaptation, 1);
FASTVRAM_CVAR(Histogram, 1);
FASTVRAM_CVAR(HistogramReduce, 1);
FASTVRAM_CVAR(VelocityFlat, 1);
FASTVRAM_CVAR(VelocityMax, 1);
FASTVRAM_CVAR(MotionBlur, 1);
FASTVRAM_CVAR(Tonemap, 1);
FASTVRAM_CVAR(Upscale, 1);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneRendering.cpp:675

Scope (from outer to inner):

file
function     void FFastVramConfig::Update

Source code excerpt:

	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_Downsample, Downsample);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_EyeAdaptation, EyeAdaptation);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_Histogram, Histogram);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_HistogramReduce, HistogramReduce);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_VelocityFlat, VelocityFlat);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_VelocityMax, VelocityMax);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_MotionBlur, MotionBlur);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_Tonemap, Tonemap);
	bDirty |= UpdateTextureFlagFromCVar(CVarFastVRam_Upscale, Upscale);

#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/SceneRendering.h:2824

Scope: file

Source code excerpt:

	ETextureCreateFlags Downsample;
	ETextureCreateFlags EyeAdaptation;
	ETextureCreateFlags Histogram;
	ETextureCreateFlags HistogramReduce;
	ETextureCreateFlags VelocityFlat;
	ETextureCreateFlags VelocityMax;
	ETextureCreateFlags MotionBlur;
	ETextureCreateFlags Tonemap;
	ETextureCreateFlags Upscale;