Add functionality for Nanite instances of a certain type to properly be filtered out if disabled by their respective ShowFlags on the view family.

#rb rune.stubbe
#preflight 62680e711638ac249e7b8a5a

#ROBOMERGE-AUTHOR: jamie.hayes
#ROBOMERGE-SOURCE: CL 19921850 via CL 19922083 via CL 19922618
#ROBOMERGE-BOT: UE5 (Release-Engine-Staging -> Main) (v943-19904690)

[CL 19925604 by jamie hayes in ue5-main branch]
This commit is contained in:
jamie hayes
2022-04-26 14:37:33 -04:00
parent 16dcf5b313
commit 292c19fe82
8 changed files with 102 additions and 25 deletions

View File

@@ -8,6 +8,7 @@
#include "NaniteDataDecode.ush"
uint NumPrimitives;
uint HiddenFilterFlags;
#if HAS_HIDDEN_PRIMITIVES_LIST
uint NumHiddenPrimitives;
@@ -54,15 +55,16 @@ void PrimitiveFilter
// GPU Scene version of IsPrimitiveHidden() from SceneVisibility.cpp
if (PrimitiveId < NumPrimitives)
{
bool bHidden = false;
FPrimitiveSceneData PrimitiveData = GetPrimitiveData(PrimitiveId);
const uint PrimitiveComponentId = PrimitiveData.PrimitiveComponentId;
// Allow arbitrary flag matching on the primitive (used for the ViewFamily's EngineShowFlags)
bool bHidden = ((PrimitiveData.NaniteFilterFlags & ~HiddenFilterFlags) != PrimitiveData.NaniteFilterFlags);
#if HAS_HIDDEN_PRIMITIVES_LIST
// If any primitives are explicitly hidden, remove them now.
BRANCH
if (NumHiddenPrimitives > 0)
if (!bHidden && NumHiddenPrimitives > 0)
{
bHidden = BinarySearchLoop(HiddenPrimitivesList, NumHiddenPrimitives, PrimitiveComponentId);
}

View File

@@ -4,6 +4,7 @@
#include "LargeWorldCoordinates.ush"
#include "OctahedralCommon.ush"
#include "/Engine/Shared/NaniteDefinitions.h"
#ifndef USE_GLOBAL_GPU_SCENE_DATA
#define USE_GLOBAL_GPU_SCENE_DATA 0
@@ -144,6 +145,7 @@ struct FPrimitiveSceneData
float3 WireframeColor; // TODO: Should refactor out all editor data into a separate buffer
float3 LevelColor; // TODO: Should refactor out all editor data into a separate buffer
uint NaniteImposterIndex;
uint NaniteFilterFlags;
float4 CustomPrimitiveData[NUM_CUSTOM_PRIMITIVE_DATA]; // TODO: Move to associated array to shrink primitive data and pack cachelines more effectively
};
@@ -183,6 +185,8 @@ FPrimitiveSceneData GetPrimitiveDataFromUniformBuffer()
PrimitiveData.InstancePayloadDataStride = Primitive.InstancePayloadDataStride;
PrimitiveData.WireframeColor = Primitive.WireframeColor;
PrimitiveData.LevelColor = Primitive.LevelColor;
PrimitiveData.NaniteImposterIndex = Primitive.NaniteImposterIndexAndFilterFlags & NANITE_IMPOSTER_INDEX_MASK;
PrimitiveData.NaniteFilterFlags = Primitive.NaniteImposterIndexAndFilterFlags >> NANITE_IMPOSTER_INDEX_NUM_BITS;
PrimitiveData.PersistentPrimitiveIndex = Primitive.PersistentPrimitiveIndex;
UNROLL
for (int DataIndex = 0; DataIndex < NUM_CUSTOM_PRIMITIVE_DATA; ++DataIndex)
@@ -292,10 +296,18 @@ FPrimitiveSceneData GetPrimitiveData(uint PrimitiveId)
PrimitiveData.InstanceLocalBoundsExtent = LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 28).xyz;
PrimitiveData.InstancePayloadDataStride = asuint(LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 28).w);
PrimitiveData.WireframeColor = LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 29).xyz;
PrimitiveData.NaniteImposterIndex = asuint(LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 29).w);
PrimitiveData.LevelColor = LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 30).xyz;
PrimitiveData.PersistentPrimitiveIndex = asint(LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 30).w);
uint NaniteImposterIndexAndFilterFlags = asuint(LoadPrimitivePrimitiveSceneDataElement(PrimitiveIndex, 29).w);
PrimitiveData.NaniteFilterFlags = NaniteImposterIndexAndFilterFlags >> NANITE_IMPOSTER_INDEX_NUM_BITS;
PrimitiveData.NaniteImposterIndex = NaniteImposterIndexAndFilterFlags & NANITE_IMPOSTER_INDEX_MASK;
if (PrimitiveData.NaniteImposterIndex == NANITE_IMPOSTER_INDEX_MASK)
{
PrimitiveData.NaniteImposterIndex = INVALID_NANITE_IMPOSTER_INDEX;
}
// TODO: Move to associated array (and editor data) to shrink primitive data and better pack cachelines
UNROLL
for (int DataIndex = 0; DataIndex < NUM_CUSTOM_PRIMITIVE_DATA; ++DataIndex)

View File

@@ -60,6 +60,12 @@
#define NANITE_MAX_GROUP_PARTS_MASK ((1 << NANITE_MAX_GROUP_PARTS_BITS) - 1)
#define NANITE_MAX_GROUP_PARTS (1 << NANITE_MAX_GROUP_PARTS_BITS)
#define NANITE_FILTER_FLAGS_NUM_BITS (4u)
#define NANITE_IMPOSTER_INDEX_NUM_BITS (32u - NANITE_FILTER_FLAGS_NUM_BITS)
#define NANITE_IMPOSTER_INDEX_MASK ((1u << NANITE_IMPOSTER_INDEX_NUM_BITS) - 1u)
#define NANITE_FILTER_FLAGS_MASK (((1u << NANITE_FILTER_FLAGS_NUM_BITS) - 1u) << NANITE_IMPOSTER_INDEX_NUM_BITS)
#define INVALID_NANITE_IMPOSTER_INDEX (0xFFFFFFFFu)
#define NANITE_MAX_BVH_NODE_FANOUT_BITS 2
#define NANITE_MAX_BVH_NODE_FANOUT_MASK ((1 << NANITE_MAX_BVH_NODE_FANOUT_BITS)-1)
#define NANITE_MAX_BVH_NODE_FANOUT (1 << NANITE_MAX_BVH_NODE_FANOUT_BITS)

View File

@@ -142,6 +142,7 @@ FPrimitiveSceneShaderData::FPrimitiveSceneShaderData(const FPrimitiveSceneProxy*
uint32 NaniteResourceID = INDEX_NONE;
uint32 NaniteHierarchyOffset = INDEX_NONE;
uint32 NaniteImposterIndex = INDEX_NONE;
uint32 NaniteFilterFlags = 0u;
bool bHasNaniteImposterData = false;
bool bEvaluateWorldPositionOffset = !OptimizedWPO;
@@ -149,6 +150,7 @@ FPrimitiveSceneShaderData::FPrimitiveSceneShaderData(const FPrimitiveSceneProxy*
if (Proxy->IsNaniteMesh())
{
Proxy->GetNaniteResourceInfo(NaniteResourceID, NaniteHierarchyOffset, NaniteImposterIndex);
NaniteFilterFlags = uint32(static_cast<const Nanite::FSceneProxyBase*>(Proxy)->GetFilterFlags());
if (OptimizedWPO)
{
bEvaluateWorldPositionOffset = static_cast<const Nanite::FSceneProxyBase*>(Proxy)->EvaluateWorldPositionOffset();
@@ -193,6 +195,7 @@ FPrimitiveSceneShaderData::FPrimitiveSceneShaderData(const FPrimitiveSceneProxy*
.NaniteResourceID(NaniteResourceID)
.NaniteHierarchyOffset(NaniteHierarchyOffset)
.NaniteImposterIndex(NaniteImposterIndex)
.NaniteFilterFlags(NaniteFilterFlags)
.PrimitiveComponentId(Proxy->GetPrimitiveComponentId().PrimIDValue)
.EditorColors(Proxy->GetWireframeColor(), Proxy->GetLevelColor());
@@ -277,7 +280,7 @@ void FPrimitiveSceneShaderData::Setup(const FPrimitiveUniformShaderParameters& P
Data[29].X = PrimitiveUniformShaderParameters.WireframeColor.X;
Data[29].Y = PrimitiveUniformShaderParameters.WireframeColor.Y;
Data[29].Z = PrimitiveUniformShaderParameters.WireframeColor.Z;
Data[29].W = *(const float*)&PrimitiveUniformShaderParameters.NaniteImposterIndex;
Data[29].W = *(const float*)&PrimitiveUniformShaderParameters.NaniteImposterIndexAndFilterFlags;
Data[30].X = PrimitiveUniformShaderParameters.LevelColor.X;
Data[30].Y = PrimitiveUniformShaderParameters.LevelColor.Y;

View File

@@ -778,11 +778,25 @@ FSceneProxy::FSceneProxy(UInstancedStaticMeshComponent* Component)
bHasRayTracingInstances = false;
}
#endif
FilterFlags = EFilterFlags::InstancedStaticMesh;
}
FSceneProxy::FSceneProxy(UHierarchicalInstancedStaticMeshComponent* Component)
: FSceneProxy(static_cast<UInstancedStaticMeshComponent*>(Component))
{
switch (Component->GetViewRelevanceType())
{
case EHISMViewRelevanceType::Grass:
FilterFlags = EFilterFlags::Grass;
break;
case EHISMViewRelevanceType::Foliage:
FilterFlags = EFilterFlags::Foliage;
break;
default:
FilterFlags = EFilterFlags::InstancedStaticMesh;
break;
}
}
FSceneProxy::~FSceneProxy()

View File

@@ -74,6 +74,16 @@ ENGINE_API bool IsSupportedBlendMode(EBlendMode Mode);
ENGINE_API bool IsSupportedMaterialDomain(EMaterialDomain Domain);
ENGINE_API bool IsWorldPositionOffsetSupported();
enum class EFilterFlags : uint8
{
None = 0u,
InstancedStaticMesh = (1u << 0u),
Foliage = (1u << 1u),
Grass = (1u << 2u),
};
ENUM_CLASS_FLAGS(EFilterFlags)
class FSceneProxyBase : public FPrimitiveSceneProxy
{
public:
@@ -151,6 +161,11 @@ public:
return MaterialMaxIndex;
}
inline EFilterFlags GetFilterFlags() const
{
return FilterFlags;
}
#if WITH_EDITOR
inline const TConstArrayView<const FHitProxyId> GetHitProxyIds() const
{
@@ -194,6 +209,7 @@ protected:
EHitProxyMode HitProxyMode = EHitProxyMode::MaterialSection;
#endif
int32 MaterialMaxIndex = INDEX_NONE;
EFilterFlags FilterFlags = EFilterFlags::None;
uint8 bHasProgrammableRaster : 1;
uint8 bEvaluateWorldPositionOffset : 1;
};

View File

@@ -13,6 +13,7 @@
#include "LightmapUniformShaderParameters.h"
#include "UnifiedBuffer.h"
#include "Containers/StaticArray.h"
#include "NaniteDefinitions.h"
/**
* The uniform shader parameters associated with a primitive.
@@ -51,7 +52,7 @@ BEGIN_GLOBAL_SHADER_PARAMETER_STRUCT(FPrimitiveUniformShaderParameters,ENGINE_AP
SHADER_PARAMETER(FVector3f, InstanceLocalBoundsExtent)
SHADER_PARAMETER(uint32, InstancePayloadDataStride)
SHADER_PARAMETER(FVector3f, WireframeColor) // Only needed for editor/development
SHADER_PARAMETER(uint32, NaniteImposterIndex)
SHADER_PARAMETER(uint32, NaniteImposterIndexAndFilterFlags)
SHADER_PARAMETER(FVector3f, LevelColor) // Only needed for editor/development
SHADER_PARAMETER(int32, PersistentPrimitiveIndex)
SHADER_PARAMETER_ARRAY(FVector4f, CustomPrimitiveData, [FCustomPrimitiveData::NumCustomPrimitiveDataFloat4s]) // Custom data per primitive that can be accessed through material expression parameters and modified through UStaticMeshComponent
@@ -115,6 +116,7 @@ public:
bVisibleInSceneCaptureOnly = false;
bHiddenInSceneCapture = false;
bForceHidden = false;
bHasNaniteImposter = false;
// Default colors
Parameters.WireframeColor = FVector3f(1.0f, 1.0f, 1.0f);
@@ -128,9 +130,9 @@ public:
Parameters.PrimitiveComponentId = ~uint32(0u);
// Nanite
Parameters.NaniteResourceID = INDEX_NONE;
Parameters.NaniteHierarchyOffset = INDEX_NONE;
Parameters.NaniteImposterIndex = INDEX_NONE;
Parameters.NaniteResourceID = INDEX_NONE;
Parameters.NaniteHierarchyOffset = INDEX_NONE;
Parameters.NaniteImposterIndexAndFilterFlags = NANITE_IMPOSTER_INDEX_MASK;
// Instance data
Parameters.InstanceSceneDataOffset = INDEX_NONE;
@@ -178,7 +180,6 @@ public:
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, PrimitiveComponentId);
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, NaniteResourceID);
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, NaniteHierarchyOffset);
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, NaniteImposterIndex);
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, LightmapUVIndex);
PRIMITIVE_UNIFORM_BUILDER_METHOD(uint32, LightmapDataIndex);
@@ -283,6 +284,24 @@ public:
return *this;
}
inline FPrimitiveUniformShaderParametersBuilder& NaniteImposterIndex(uint32 ImposterIndex)
{
bHasNaniteImposter = ImposterIndex != INDEX_NONE;
check(!bHasNaniteImposter || ImposterIndex < NANITE_IMPOSTER_INDEX_MASK);
Parameters.NaniteImposterIndexAndFilterFlags = (Parameters.NaniteImposterIndexAndFilterFlags & NANITE_FILTER_FLAGS_MASK) | (ImposterIndex & NANITE_IMPOSTER_INDEX_MASK);
return *this;
}
inline FPrimitiveUniformShaderParametersBuilder& NaniteFilterFlags(uint32 FilterFlags)
{
check(FilterFlags < (1u << NANITE_FILTER_FLAGS_NUM_BITS));
Parameters.NaniteImposterIndexAndFilterFlags = (FilterFlags << NANITE_IMPOSTER_INDEX_NUM_BITS) | (Parameters.NaniteImposterIndexAndFilterFlags & NANITE_IMPOSTER_INDEX_MASK);
return *this;
}
inline const FPrimitiveUniformShaderParameters& Build()
{
const FLargeWorldRenderPosition AbsoluteWorldPosition(AbsoluteLocalToWorld.GetOrigin());
@@ -361,7 +380,7 @@ public:
Parameters.Flags |= ((LightingChannels & 0x1) != 0) ? PRIMITIVE_SCENE_DATA_FLAG_LIGHTING_CHANNEL_0 : 0u;
Parameters.Flags |= ((LightingChannels & 0x2) != 0) ? PRIMITIVE_SCENE_DATA_FLAG_LIGHTING_CHANNEL_1 : 0u;
Parameters.Flags |= ((LightingChannels & 0x4) != 0) ? PRIMITIVE_SCENE_DATA_FLAG_LIGHTING_CHANNEL_2 : 0u;
Parameters.Flags |= (Parameters.NaniteImposterIndex != INDEX_NONE) ? PRIMITIVE_SCENE_DATA_FLAG_HAS_NANITE_IMPOSTER : 0u;
Parameters.Flags |= bHasNaniteImposter ? PRIMITIVE_SCENE_DATA_FLAG_HAS_NANITE_IMPOSTER : 0u;
Parameters.Flags |= bHasInstanceLocalBounds ? PRIMITIVE_SCENE_DATA_FLAG_HAS_INSTANCE_LOCAL_BOUNDS : 0u;
Parameters.Flags |= bCastShadow ? PRIMITIVE_SCENE_DATA_FLAG_CAST_SHADOWS : 0u;
Parameters.Flags |= bCastContactShadow ? PRIMITIVE_SCENE_DATA_FLAG_HAS_CAST_CONTACT_SHADOW : 0u;
@@ -412,6 +431,7 @@ private:
uint32 bVisibleInSceneCaptureOnly : 1;
uint32 bHiddenInSceneCapture : 1;
uint32 bForceHidden : 1;
uint32 bHasNaniteImposter : 1;
};
inline TUniformBufferRef<FPrimitiveUniformShaderParameters> CreatePrimitiveUniformBufferImmediate(

View File

@@ -2,6 +2,7 @@
#include "NaniteCullRaster.h"
#include "NaniteVisualizationData.h"
#include "NaniteSceneProxy.h"
#include "RHI.h"
#include "SceneUtils.h"
#include "ScenePrivate.h"
@@ -268,19 +269,6 @@ class FPrimitiveFilter_CS : public FNaniteGlobalShader
using FPermutationDomain = TShaderPermutationDomain<FHiddenPrimitivesListDim, FShowOnlyPrimitivesListDim>;
static bool ShouldCompilePermutation(const FGlobalShaderPermutationParameters& Parameters)
{
FPermutationDomain PermutationVector(Parameters.PermutationId);
if (!PermutationVector.Get<FHiddenPrimitivesListDim>() && !PermutationVector.Get<FShowOnlyPrimitivesListDim>())
{
// Don't compile a permutation with both buffers disabled
return false;
}
return FNaniteGlobalShader::ShouldCompilePermutation(Parameters);
}
static void ModifyCompilationEnvironment(const FGlobalShaderPermutationParameters& Parameters, FShaderCompilerEnvironment& OutEnvironment)
{
FNaniteGlobalShader::ModifyCompilationEnvironment(Parameters, OutEnvironment);
@@ -291,6 +279,7 @@ class FPrimitiveFilter_CS : public FNaniteGlobalShader
BEGIN_SHADER_PARAMETER_STRUCT(FParameters, )
SHADER_PARAMETER(uint32, NumPrimitives)
SHADER_PARAMETER(uint32, HiddenFilterFlags)
SHADER_PARAMETER(uint32, NumHiddenPrimitives)
SHADER_PARAMETER(uint32, NumShowOnlyPrimitives)
@@ -1374,12 +1363,26 @@ void AddPass_PrimitiveFilter(
const uint32 PrimitiveCount = uint32(Scene.Primitives.Num());
const uint32 HiddenPrimitiveCount = SceneView.HiddenPrimitives.Num();
const uint32 ShowOnlyPrimitiveCount = SceneView.ShowOnlyPrimitives.IsSet() ? SceneView.ShowOnlyPrimitives->Num() : 0u;
EFilterFlags HiddenFilterFlags = EFilterFlags::None;
if (!SceneView.Family->EngineShowFlags.InstancedStaticMeshes)
{
HiddenFilterFlags |= EFilterFlags::InstancedStaticMesh;
}
if (!SceneView.Family->EngineShowFlags.InstancedFoliage)
{
HiddenFilterFlags |= EFilterFlags::Foliage;
}
if (!SceneView.Family->EngineShowFlags.InstancedGrass)
{
HiddenFilterFlags |= EFilterFlags::Grass;
}
CullingContext.PrimitiveFilterBuffer = nullptr;
CullingContext.HiddenPrimitivesBuffer = nullptr;
CullingContext.ShowOnlyPrimitivesBuffer = nullptr;
if (CVarNaniteFilterPrimitives.GetValueOnRenderThread() != 0 && (HiddenPrimitiveCount + ShowOnlyPrimitiveCount) > 0)
if (CVarNaniteFilterPrimitives.GetValueOnRenderThread() != 0 && ((HiddenPrimitiveCount + ShowOnlyPrimitiveCount) > 0 || HiddenFilterFlags != EFilterFlags::None))
{
check(PrimitiveCount > 0);
const uint32 DWordCount = FMath::DivideAndRoundUp(PrimitiveCount, 32u); // 32 primitive bits per uint32
@@ -1450,6 +1453,7 @@ void AddPass_PrimitiveFilter(
FPrimitiveFilter_CS::FParameters* PassParameters = GraphBuilder.AllocParameters<FPrimitiveFilter_CS::FParameters>();
PassParameters->NumPrimitives = PrimitiveCount;
PassParameters->HiddenFilterFlags = uint32(HiddenFilterFlags);
PassParameters->NumHiddenPrimitives = FMath::RoundUpToPowerOfTwo(HiddenPrimitiveCount);
PassParameters->NumShowOnlyPrimitives = FMath::RoundUpToPowerOfTwo(ShowOnlyPrimitiveCount);
PassParameters->GPUSceneParameters = GPUSceneParameters;