r.HairStrands.ContinuousDecimationReordering
r.HairStrands.ContinuousDecimationReordering
#Overview
name: r.HairStrands.ContinuousDecimationReordering
This variable is created as a Console Variable (cvar).
- type:
Var
- help:
Enable strand reordering to allow Continuous LOD. Experimental
It is referenced in 10
C++ source files.
#Summary
#Usage in the C++ source code
The purpose of r.HairStrands.ContinuousDecimationReordering is to enable strand reordering for continuous Level of Detail (LOD) in the hair rendering system of Unreal Engine 5. This is an experimental feature.
This setting variable is primarily used in the HairStrands subsystem, which is part of the rendering module in Unreal Engine 5. It affects various components related to hair rendering, including resource management, debug visualization, and buffer swapping.
The value of this variable is set through the console variable system (CVarHairStrandsContinuousDecimationReordering). It’s a read-only variable, meaning its value can’t be changed at runtime.
This variable interacts with several other components of the hair rendering system:
- It affects the allocation and management of hair strand buffers, particularly for deformed roots and samples.
- It influences the buffer swapping mechanism in the hair rendering pipeline.
- It impacts the debug visualization of hair strands.
Developers must be aware that:
- This is an experimental feature and may not be fully stable.
- Enabling this feature affects memory allocation and runtime behavior of the hair rendering system.
- It’s a read-only variable, so it can’t be changed dynamically during gameplay.
Best practices when using this variable:
- Only enable it if you specifically need continuous LOD for hair strands.
- Test thoroughly when enabled, as it may impact performance and visual quality.
- Be prepared for potential instability or unexpected behavior, given its experimental nature.
Regarding the associated variable CVarHairStrandsContinuousDecimationReordering:
This is the actual console variable that controls the r.HairStrands.ContinuousDecimationReordering setting. It’s an integer variable, where a value greater than 0 enables the feature. It’s defined with the ECVF_RenderThreadSafe and ECVF_ReadOnly flags, indicating it’s safe to access from the render thread and can’t be modified at runtime.
The IsHairStrandContinuousDecimationReorderingEnabled() function checks the value of this console variable to determine if the feature is enabled. This function is used throughout the hair strands rendering code to conditionally execute logic related to continuous LOD and buffer management.
When working with this feature, developers should use the IsHairStrandContinuousDecimationReorderingEnabled() function to check if the feature is enabled, rather than directly accessing the console variable.
#References in C++ code
#Callsites
This variable is referenced in the following C++ source code:
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/HairStrands/HairStrandsInterface.cpp:68
Scope: file
Source code excerpt:
static TAutoConsoleVariable<int32> CVarHairStrandsContinuousDecimationReordering(
TEXT("r.HairStrands.ContinuousDecimationReordering"), 0,
TEXT("Enable strand reordering to allow Continuous LOD. Experimental"),
ECVF_RenderThreadSafe | ECVF_ReadOnly);
static TAutoConsoleVariable<int32> CVarHairStrandsVisibilityComputeRaster(
TEXT("r.HairStrands.Visibility.ComputeRaster"), 0,
TEXT("Hair Visiblity uses raster compute. Experimental"),
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/GroomDebug.cpp:200
Scope (from outer to inner):
file
function static void AddDebugProjectionHairPass
Source code excerpt:
}
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled() && !DeformedLODDatas.DeformedUniqueTrianglePositionBuffer[1].Buffer)
{
return;
}
const FIntPoint Resolution(Viewport.Width(), Viewport.Height());
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/GroomManager.cpp:2221
Scope (from outer to inner):
file
function static void RunHairBufferSwap
Source code excerpt:
if (Instance->Strands.DeformedResource) { Instance->Strands.DeformedResource->SwapBuffer(); }
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled())
{
if (Instance->Guides.DeformedRootResource) { Instance->Guides.DeformedRootResource->SwapBuffer(); }
if (Instance->Strands.DeformedRootResource) { Instance->Strands.DeformedRootResource->SwapBuffer(); }
}
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/GroomResources.cpp:1708
Scope (from outer to inner):
file
function void FHairStrandsLODDeformedRootResource::InternalAllocate
Source code excerpt:
InternalCreateStructuredBufferRDG<FHairStrandsMeshTrianglePositionFormat>(GraphBuilder, RBFEntryCount, MeshSampleWeightsBuffer[0], ToHairResourceDebugName(HAIRSTRANDS_RESOUCE_NAME(CurveType, Hair.StrandsRootDeformed_MeshSampleWeightsBuffer0), ResourceName), OwnerName, EHairResourceUsageType::Dynamic);
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled())
{
InternalCreateStructuredBufferRDG<FHairStrandsMeshTrianglePositionFormat>(GraphBuilder, SampleCount, DeformedSamplePositionsBuffer[1], ToHairResourceDebugName(HAIRSTRANDS_RESOUCE_NAME(CurveType, Hair.StrandsRootDeformed_DeformedSamplePositionsBuffer1), ResourceName), OwnerName, EHairResourceUsageType::Dynamic);
InternalCreateStructuredBufferRDG<FHairStrandsMeshTrianglePositionFormat>(GraphBuilder, RBFEntryCount, MeshSampleWeightsBuffer[1], ToHairResourceDebugName(HAIRSTRANDS_RESOUCE_NAME(CurveType, Hair.StrandsRootDeformed_MeshSampleWeightsBuffer1), ResourceName), OwnerName, EHairResourceUsageType::Dynamic);
}
}
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/GroomResources.cpp:1718
Scope (from outer to inner):
file
function void FHairStrandsLODDeformedRootResource::InternalAllocate
Source code excerpt:
InternalCreateVertexBufferRDG<FHairStrandsMeshTrianglePositionFormat>(GraphBuilder, RootCount * 3, DeformedUniqueTrianglePositionBuffer[0], ToHairResourceDebugName(HAIRSTRANDS_RESOUCE_NAME(CurveType, Hair.StrandsRootDeformed_DeformedUniqueTrianglePosition0Buffer0), ResourceName), OwnerName, EHairResourceUsageType::Dynamic);
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled())
{
InternalCreateVertexBufferRDG<FHairStrandsMeshTrianglePositionFormat>(GraphBuilder, RootCount * 3, DeformedUniqueTrianglePositionBuffer[1], ToHairResourceDebugName(HAIRSTRANDS_RESOUCE_NAME(CurveType, Hair.StrandsRootDeformed_DeformedUniqueTrianglePosition0Buffer1), ResourceName), OwnerName, EHairResourceUsageType::Dynamic);
}
}
}
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Private/GroomResources.cpp:1734
Scope (from outer to inner):
file
function void FHairStrandsLODDeformedRootResource::InternalRelease
Source code excerpt:
MeshSampleWeightsBuffer[0].Release();
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled())
{
DeformedUniqueTrianglePositionBuffer[1].Release();
DeformedSamplePositionsBuffer[1].Release();
MeshSampleWeightsBuffer[1].Release();
}
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Public/GroomResources.h:516
Scope (from outer to inner):
file
function uint32 GetResourcesSize
Source code excerpt:
Total += GetBufferTotalNumBytes(MeshSampleWeightsBuffer[0]);
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
if (IsHairStrandContinuousDecimationReorderingEnabled())
{
Total += GetBufferTotalNumBytes(DeformedUniqueTrianglePositionBuffer[1]);
Total += GetBufferTotalNumBytes(DeformedSamplePositionsBuffer[1]);
Total += GetBufferTotalNumBytes(MeshSampleWeightsBuffer[1]);
}
#Loc: <Workspace>/Engine/Plugins/Runtime/HairStrands/Source/HairStrandsCore/Public/GroomResources.h:553
Scope: file
Source code excerpt:
};
// Double buffering is disabled by default unless the read-only cvar r.HairStrands.ContinuousDecimationReordering is set
inline uint32 GetIndex(EFrameType T) const { return T == EFrameType::Current ? CurrentIndex : 1u - CurrentIndex; }
inline const FRDGExternalBuffer& GetDeformedUniqueTrianglePositionBuffer(EFrameType T) const { return IsHairStrandContinuousDecimationReorderingEnabled() ? DeformedUniqueTrianglePositionBuffer[GetIndex(T)] : DeformedUniqueTrianglePositionBuffer[0]; }
inline const FRDGExternalBuffer& GetDeformedSamplePositionsBuffer(EFrameType T) const { return IsHairStrandContinuousDecimationReorderingEnabled() ? DeformedSamplePositionsBuffer[GetIndex(T)] : DeformedSamplePositionsBuffer[0]; }
inline const FRDGExternalBuffer& GetMeshSampleWeightsBuffer(EFrameType T) const { return IsHairStrandContinuousDecimationReorderingEnabled() ? MeshSampleWeightsBuffer[GetIndex(T)] : MeshSampleWeightsBuffer[0]; }
inline void SwapBuffer() { CurrentIndex = 1u - CurrentIndex; }
#Associated Variable and Callsites
This variable is associated with another variable named CVarHairStrandsContinuousDecimationReordering
. They share the same value. See the following C++ source code.
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/HairStrands/HairStrandsInterface.cpp:67
Scope: file
Source code excerpt:
ECVF_RenderThreadSafe);
static TAutoConsoleVariable<int32> CVarHairStrandsContinuousDecimationReordering(
TEXT("r.HairStrands.ContinuousDecimationReordering"), 0,
TEXT("Enable strand reordering to allow Continuous LOD. Experimental"),
ECVF_RenderThreadSafe | ECVF_ReadOnly);
static TAutoConsoleVariable<int32> CVarHairStrandsVisibilityComputeRaster(
TEXT("r.HairStrands.Visibility.ComputeRaster"), 0,
#Loc: <Workspace>/Engine/Source/Runtime/Renderer/Private/HairStrands/HairStrandsInterface.cpp:313
Scope (from outer to inner):
file
function bool IsHairStrandContinuousDecimationReorderingEnabled
Source code excerpt:
{
//NB this is a readonly cvar - and causes changes in platform data and runtime allocations
return CVarHairStrandsContinuousDecimationReordering.GetValueOnAnyThread() > 0;
}
bool IsHairVisibilityComputeRasterEnabled()
{
return CVarHairStrandsVisibilityComputeRaster.GetValueOnAnyThread() == 1;
}