ShowFlag.ShaderComplexity
ShowFlag.ShaderComplexity
#Overview
name: ShowFlag.ShaderComplexity
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Allows to override a specific showflag (works in editor and game, \
It is referenced in 24
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of ShowFlag.ShaderComplexity is to enable a visualization mode that renders the scene colored by shader complexity. This is primarily used for performance analysis and optimization of shaders in the rendering system.
ShowFlag.ShaderComplexity is used across various Unreal Engine subsystems and modules, including:
- The Renderer module
- The Engine module
- The Niagara plugin (for particle effects)
- The MediaIOCore plugin
The value of this variable is typically set through the engine’s show flags system, which allows developers to toggle various debug visualization modes.
This variable interacts with several other variables and systems:
- It’s often used in conjunction with EngineShowFlags.QuadOverdraw and EngineShowFlags.ShaderComplexityWithQuadOverdraw for more detailed shader complexity visualization.
- It affects the behavior of the base pass rendering, post-processing, and decal rendering.
- It can disable certain features like DBuffer decals when enabled.
Developers should be aware of the following when using this variable:
- Enabling shader complexity visualization will override normal scene rendering, so it should only be used for debugging and optimization purposes.
- It may have performance implications when enabled, as it requires additional processing to visualize shader complexity.
- It can affect other rendering features and may disable some post-processing effects.
Best practices for using this variable include:
- Use it in conjunction with profiling tools to identify areas of high shader complexity.
- Remember to disable it when not actively debugging shader performance.
- Be aware of its interactions with other debug visualization modes and rendering features.
The associated variable ShaderComplexity is used in similar contexts and shares the same value as ShowFlag.ShaderComplexity. It’s primarily used in conditional statements to determine whether shader complexity visualization is enabled and to adjust rendering behavior accordingly. The same considerations and best practices apply to this variable as well.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:207
Scope: file
Source code excerpt:
SHOWFLAG_FIXED_IN_SHIPPING(0, LightComplexity, SFG_Hidden, NSLOCTEXT("UnrealEd", "LightComplexitySF", "Light Complexity"))
/** needed for VMI_ShaderComplexity, render world colored by shader complexity */
SHOWFLAG_FIXED_IN_SHIPPING(0, ShaderComplexity, SFG_Hidden, NSLOCTEXT("UnrealEd", "ShaderComplexitySF", "Shader Complexity"))
/** needed for VMI_StationaryLightOverlap, render world colored by stationary light overlap */
SHOWFLAG_FIXED_IN_SHIPPING(0, StationaryLightOverlap, SFG_Hidden, NSLOCTEXT("UnrealEd", "StationaryLightOverlapSF", "Stationary Light Overlap"))
/** needed for VMI_LightmapDensity and VMI_LitLightmapDensity, render checkerboard material with UVs scaled by lightmap resolution w. color tint for world-space lightmap density */
SHOWFLAG_FIXED_IN_SHIPPING(0, LightMapDensity, SFG_Hidden, NSLOCTEXT("UnrealEd", "LightMapDensitySF", "Light Map Density"))
/** Render streaming bounding volumes for the currently selected texture */
SHOWFLAG_FIXED_IN_SHIPPING(0, StreamingBounds, SFG_Advanced, NSLOCTEXT("UnrealEd", "StreamingBoundsSF", "Streaming Bounds"))
#Associated Variable and Callsites
This variable is associated with another variable named ShaderComplexity
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Plugins/FX/Niagara/Source/Niagara/Private/NiagaraRendererMeshes.cpp:343
Scope (from outer to inner):
file
function void FNiagaraRendererMeshes::PrepareParticleMeshRenderData
Source code excerpt:
// For main pass scene captures we exclude the batches if they are translucent
const bool bIsExcludedViewMode = AllowDebugViewmodes() &&
(ViewFamily.EngineShowFlags.Wireframe || ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.ShaderComplexityWithQuadOverdraw);
ParticleMeshRenderData.bIsGpuLowLatencyTranslucency =
bGpuLowLatencyTranslucency &&
GpuReadyTickStage >= CurrentParticleData->GetGPUDataReadyStage() &&
!bIsExcludedViewMode &&
!SceneProxy->CastsVolumetricTranslucentShadow() &&
ParticleMeshRenderData.DynamicDataMesh->Materials.Num() > 0 &&
#Loc: <Workspace>/Engine/Plugins/Media/MediaIOFramework/Source/MediaIOCore/Private/MediaCaptureSceneViewExtension.h:53
Scope (from outer to inner):
file
class class FMediaCaptureSceneViewExtension : public FSceneViewExtensionBase
function virtual void SetupView
Source code excerpt:
!InView.Family->EngineShowFlags.VisualizeVolumetricCloudConservativeDensity &&
!InView.Family->EngineShowFlags.VisualizeVolumetricCloudEmptySpaceSkipping &&
!InView.Family->EngineShowFlags.ShaderComplexity;
}
else
{
bPostProcessingEnabled = InView.Family->EngineShowFlags.PostProcessing && !InView.Family->EngineShowFlags.ShaderComplexity && IsMobileHDR();
}
if (CapturePhase != EMediaCapturePhase::BeforePostProcessing && CapturePhase != EMediaCapturePhase::EndFrame)
{
if (!bPostProcessingEnabled)
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/SceneView.cpp:3056
Scope (from outer to inner):
file
function EDebugViewShaderMode FSceneViewFamily::ChooseDebugViewShaderMode
Source code excerpt:
EDebugViewShaderMode FSceneViewFamily::ChooseDebugViewShaderMode() const
{
if (EngineShowFlags.ShaderComplexity)
{
if (EngineShowFlags.QuadOverdraw)
{
return DVSM_QuadComplexity;
}
else if (EngineShowFlags.ShaderComplexityWithQuadOverdraw)
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ShowFlags.cpp:727
Scope (from outer to inner):
file
function EViewModeIndex FindViewMode
Source code excerpt:
return VMI_StationaryLightOverlap;
}
// Test QuadComplexity before ShaderComplexity because QuadComplexity also use ShaderComplexity
else if (EngineShowFlags.QuadOverdraw)
{
return VMI_QuadOverdraw;
}
else if (EngineShowFlags.ShaderComplexityWithQuadOverdraw)
{
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Private/ShowFlags.cpp:756
Scope: file
Source code excerpt:
return VMI_RequiredTextureResolution;
}
else if (EngineShowFlags.ShaderComplexity)
{
return VMI_ShaderComplexity;
}
else if (EngineShowFlags.VisualizeLightCulling)
{
return VMI_LightComplexity;
#Loc: <Workspace>/Engine/Source/Runtime/Engine/Public/ShowFlagsValues.inl:207
Scope: file
Source code excerpt:
SHOWFLAG_FIXED_IN_SHIPPING(0, LightComplexity, SFG_Hidden, NSLOCTEXT("UnrealEd", "LightComplexitySF", "Light Complexity"))
/** needed for VMI_ShaderComplexity, render world colored by shader complexity */
SHOWFLAG_FIXED_IN_SHIPPING(0, ShaderComplexity, SFG_Hidden, NSLOCTEXT("UnrealEd", "ShaderComplexitySF", "Shader Complexity"))
/** needed for VMI_StationaryLightOverlap, render world colored by stationary light overlap */
SHOWFLAG_FIXED_IN_SHIPPING(0, StationaryLightOverlap, SFG_Hidden, NSLOCTEXT("UnrealEd", "StationaryLightOverlapSF", "Stationary Light Overlap"))
/** needed for VMI_LightmapDensity and VMI_LitLightmapDensity, render checkerboard material with UVs scaled by lightmap resolution w. color tint for world-space lightmap density */
SHOWFLAG_FIXED_IN_SHIPPING(0, LightMapDensity, SFG_Hidden, NSLOCTEXT("UnrealEd", "LightMapDensitySF", "Light Map Density"))
/** Render streaming bounding volumes for the currently selected texture */
SHOWFLAG_FIXED_IN_SHIPPING(0, StreamingBounds, SFG_Advanced, NSLOCTEXT("UnrealEd", "StreamingBoundsSF", "Streaming Bounds"))
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1028
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePass
Source code excerpt:
// Always perform a full buffer clear for wireframe, shader complexity view mode, and stationary light overlap viewmode.
if (ViewFamily.EngineShowFlags.Wireframe || ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.StationaryLightOverlap)
{
bRequiresRHIClear = true;
bRequiresFarZQuadClear = false;
}
const bool bIsWireframeRenderpass = ViewFamily.EngineShowFlags.Wireframe && FSceneRenderer::ShouldCompositeEditorPrimitives(InViews[0]);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1045
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePass
Source code excerpt:
ViewFamily.EngineShowFlags.MeshUVDensityAccuracy ||
ViewFamily.EngineShowFlags.PrimitiveDistanceAccuracy ||
ViewFamily.EngineShowFlags.ShaderComplexity ||
ViewFamily.EngineShowFlags.LODColoration ||
ViewFamily.EngineShowFlags.HLODColoration);
const bool bForwardShadingEnabled = IsForwardShadingEnabled(SceneTextures.Config.ShaderPlatform);
const FExclusiveDepthStencil ExclusiveDepthStencil(BasePassDepthStencilAccess);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1062
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePass
Source code excerpt:
if (bRequiresRHIClear)
{
if (ViewFamily.EngineShowFlags.ShaderComplexity && SceneTextures.QuadOverdraw)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(SceneTextures.QuadOverdraw), FUintVector4(0, 0, 0, 0));
}
if (ViewFamily.EngineShowFlags.ShaderComplexity || ViewFamily.EngineShowFlags.StationaryLightOverlap)
{
SceneColorClearValue = FLinearColor(0, 0, 0, kSceneColorClearAlpha);
}
else
{
SceneColorClearValue = FLinearColor(InViews[0].BackgroundColor.R, InViews[0].BackgroundColor.G, InViews[0].BackgroundColor.B, kSceneColorClearAlpha);
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1364
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePassInternal
Source code excerpt:
case DVSM_ShaderComplexityBleedingQuadOverhead: // Show shader complexity with quad overdraw bleeding the PS instruction count over the quad.
case DVSM_QuadComplexity: // Show quad overdraw only.
NaniteDebugViewMode = Nanite::EDebugViewMode::ShaderComplexity;
break;
default:
break;
}
}
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1489
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePassInternal
Source code excerpt:
FMeshPassProcessorRenderState DrawRenderState;
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
PassParameters->View = View.GetShaderParameters();
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, bLumenGIEnabled);
PassParameters->RenderTargets = BasePassRenderTargets;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/BasePassRendering.cpp:1561
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::RenderBasePassInternal
Source code excerpt:
FMeshPassProcessorRenderState DrawRenderState;
SetupBasePassState(BasePassDepthStencilAccess, ViewFamily.EngineShowFlags.ShaderComplexity, DrawRenderState);
FOpaqueBasePassParameters* PassParameters = GraphBuilder.AllocParameters<FOpaqueBasePassParameters>();
PassParameters->View = View.GetShaderParameters();
PassParameters->ReflectionCapture = View.ReflectionCaptureUniformBuffer;
PassParameters->BasePass = CreateOpaqueBasePassUniformBuffer(GraphBuilder, View, ViewIndex, ForwardBasePassTextures, DBufferTextures, bLumenGIEnabled);
PassParameters->RenderTargets = BasePassRenderTargets;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/CompositionLighting/PostProcessDeferredDecals.cpp:63
Scope (from outer to inner):
file
function bool IsDBufferEnabled
Source code excerpt:
return IsUsingDBuffers(ShaderPlatform)
&& AreDecalsEnabled(ViewFamily)
&& !ViewFamily.EngineShowFlags.ShaderComplexity;
}
IMPLEMENT_STATIC_UNIFORM_BUFFER_STRUCT(FDecalPassUniformParameters, "DecalPass", SceneTextures);
FDeferredDecalPassTextures GetDeferredDecalPassTextures(
FRDGBuilder& GraphBuilder,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/CompositionLighting/PostProcessDeferredDecals.cpp:602
Scope (from outer to inner):
file
function void AddDeferredDecalPass
Source code excerpt:
const bool bVisibleDecalsInView = MeshDecalCount > 0 || SortedDecalCount > 0;
const bool bShaderComplexity = View.Family->EngineShowFlags.ShaderComplexity;
const bool bStencilSizeThreshold = CVarStencilSizeThreshold.GetValueOnRenderThread() >= 0;
// Attempt to clear the D-Buffer if it's appropriate for this view.
const EDecalDBufferMaskTechnique DBufferMaskTechnique = GetDBufferMaskTechnique(ShaderPlatform);
const auto RenderDecals = [&](uint32 DecalIndexBegin, uint32 DecalIndexEnd, EDecalRenderTargetMode RenderTargetMode)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/CompositionLighting/PostProcessMeshDecals.cpp:242
Scope (from outer to inner):
file
function bool FMeshDecalMeshProcessor::TryAddMeshBatch
Source code excerpt:
{
// Deferred decals can only use translucent blend mode
if (ViewIfDynamicMeshCommand->Family->EngineShowFlags.ShaderComplexity)
{
// If we are in the translucent pass then override the blend mode, otherwise maintain additive blending.
PassDrawRenderState.SetBlendState(TStaticBlendState<CW_RGBA, BO_Add, BF_One, BF_One, BO_Add, BF_Zero, BF_One>::GetRHI());
}
else if (ViewIfDynamicMeshCommand->Family->GetDebugViewShaderMode() != DVSM_OutputMaterialTextureScales)
{
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DecalRenderingShared.cpp:337
Scope (from outer to inner):
file
function FTransientDecalRenderDataList BuildVisibleDecalList
Source code excerpt:
// Don't draw for shader complexity mode.
// todo: Handle shader complexity mode for deferred decal.
if (View.Family->EngineShowFlags.ShaderComplexity)
{
return {};
}
FTransientDecalRenderDataList OutVisibleDecals;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/DeferredShadingRenderer.cpp:1681
Scope (from outer to inner):
file
function void FDeferredShadingSceneRenderer::Render
Source code excerpt:
// Use read-only depth in the base pass if we have a full depth prepass.
const bool bAllowReadOnlyDepthBasePass = bIsEarlyDepthComplete
&& !ViewFamily.EngineShowFlags.ShaderComplexity
&& !ViewFamily.UseDebugViewPS()
&& !ViewFamily.EngineShowFlags.Wireframe
&& !ViewFamily.EngineShowFlags.LightMapDensity;
const FExclusiveDepthStencil::Type BasePassDepthStencilAccess =
bAllowReadOnlyDepthBasePass
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/MobileShadingRenderer.cpp:1065
Scope (from outer to inner):
file
function void FMobileSceneRenderer::Render
Source code excerpt:
{
#if WITH_DEBUG_VIEW_MODES
if (ViewFamily.UseDebugViewPS() && ViewFamily.EngineShowFlags.ShaderComplexity && SceneTextures.QuadOverdraw)
{
AddClearUAVPass(GraphBuilder, GraphBuilder.CreateUAV(SceneTextures.QuadOverdraw), FUintVector4(0, 0, 0, 0));
}
#endif
if (bUseVirtualTexturing)
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteVisualize.h:35
Scope (from outer to inner):
file
namespace Nanite
Source code excerpt:
None = 0,
Wireframe = 1,
ShaderComplexity = 2,
LightmapDensity = 3,
PrimitiveColor = 4,
};
void RenderDebugViewMode(
FRDGBuilder& GraphBuilder,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:186
Scope (from outer to inner):
file
function bool IsPostProcessingEnabled
Source code excerpt:
!View.Family->EngineShowFlags.VisualizeVolumetricCloudConservativeDensity &&
!View.Family->EngineShowFlags.VisualizeVolumetricCloudEmptySpaceSkipping &&
!View.Family->EngineShowFlags.ShaderComplexity;
}
else
{
return View.Family->EngineShowFlags.PostProcessing && !View.Family->EngineShowFlags.ShaderComplexity && IsMobileHDR();
}
}
bool IsPostProcessingWithAlphaChannelSupported()
{
return CVarPostProcessingPropagateAlpha.GetValueOnAnyThread() != 0;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:1817
Scope (from outer to inner):
file
function void AddDebugViewPostProcessingPasses
Source code excerpt:
// Some view modes do not actually output a color so they should not be tonemapped.
const bool bTonemapAfter = View.Family->EngineShowFlags.RayTracingDebug || View.Family->EngineShowFlags.VisualizeGPUSkinCache;
const bool bTonemapBefore = !bTonemapAfter && !View.Family->EngineShowFlags.ShaderComplexity;
const bool bViewFamilyOutputInHDR = View.Family->RenderTarget->GetSceneHDREnabled();
enum class EPass : uint32
{
Visualize,
TonemapAfter,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:2207
Scope (from outer to inner):
file
function void AddMobilePostProcessingPasses
Source code excerpt:
bool bUseMobileDof = bUseDof && !View.FinalPostProcessSettings.bMobileHQGaussian;
bool bUseToneMapper = !View.Family->EngineShowFlags.ShaderComplexity && (IsMobileHDR() || IsMobileColorsRGB());
bool bUseHighResolutionScreenshotMask = IsHighResolutionScreenshotMaskEnabled(View);
bool bShouldPrimaryUpscale = (View.PrimaryScreenPercentageMethod == EPrimaryScreenPercentageMethod::SpatialUpscale && View.UnscaledViewRect != View.ViewRect) || PaniniConfig.IsEnabled();
bShouldPrimaryUpscale |= View.Family->GetPrimarySpatialUpscalerInterface() != nullptr;
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/PostProcess/PostProcessing.cpp:2230
Scope (from outer to inner):
file
function void AddMobilePostProcessingPasses
Source code excerpt:
PassSequence.SetEnabled(EPass::SecondaryUpscale, View.Family->GetSecondarySpatialUpscalerInterface() != nullptr);
PassSequence.SetEnabled(EPass::Visualize, View.Family->EngineShowFlags.ShaderComplexity);
PassSequence.SetEnabled(EPass::HMDDistortion, View.Family->EngineShowFlags.StereoRendering && View.Family->EngineShowFlags.HMDDistortion);
// Always evaluate custom post processes
// The scene color will be decoded at the first post-process material and output linear color space for the following passes
// bMetalMSAAHDRDecode will be set to false if there is any post-process material exist