Files
UnrealEngine/Engine/Source/Runtime/Renderer/Private/Nanite/NaniteVisibility.h
2025-05-18 13:04:45 +08:00

182 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "NaniteShared.h"
//#include "NaniteCullRaster.h"
struct FNaniteVisibilityQuery;
class FNaniteVisibilityResults
{
friend class FNaniteVisibility;
friend struct FNaniteVisibilityQuery;
public:
FNaniteVisibilityResults() = default;
bool IsRasterBinVisible(uint16 BinIndex) const;
bool IsShadingBinVisible(uint16 BinIndex) const;
FORCEINLINE bool IsRasterTestValid() const
{
return bRasterTestValid;
}
FORCEINLINE bool IsShadingTestValid() const
{
return bShadingTestValid;
}
FORCEINLINE void GetRasterBinStats(uint32& OutNumVisible, uint32& OutNumTotal) const
{
OutNumTotal = TotalRasterBins;
OutNumVisible = IsRasterTestValid() ? VisibleRasterBins : OutNumTotal;
}
FORCEINLINE void GetShadingBinStats(uint32& OutNumVisible, uint32& OutNumTotal) const
{
OutNumTotal = TotalShadingBins;
OutNumVisible = IsShadingTestValid() ? VisibleShadingBins : OutNumTotal;
}
FORCEINLINE void SetRasterBinIndexTranslator(const FNaniteRasterBinIndexTranslator InTranslator)
{
BinIndexTranslator = InTranslator;
}
FORCEINLINE bool ShouldRenderCustomDepthPrimitive(uint32 PrimitiveId) const
{
if (!bRasterTestValid && !bShadingTestValid)
{
// no valid test results, so we didn't visibility test any primitives
return true;
}
return VisibleCustomDepthPrimitives.Contains(PrimitiveId);
}
FORCEINLINE const TBitArray<>& GetRasterBinVisibility() const
{
return RasterBinVisibility;
}
FORCEINLINE const TBitArray<>& GetShadingBinVisibility() const
{
return ShadingBinVisibility;
}
private:
TBitArray<> RasterBinVisibility;
TBitArray<> ShadingBinVisibility;
TSet<uint32, DefaultKeyFuncs<uint32>, SceneRenderingSetAllocator> VisibleCustomDepthPrimitives;
FNaniteRasterBinIndexTranslator BinIndexTranslator;
uint32 TotalRasterBins = 0;
uint32 TotalShadingBins = 0;
uint32 VisibleRasterBins = 0;
uint32 VisibleShadingBins = 0;
bool bRasterTestValid = false;
bool bShadingTestValid = false;
};
class FNaniteVisibility
{
friend class FNaniteVisibilityTask;
public:
struct FRasterBin
{
uint16 Primary = 0xFFFFu;
uint16 Fallback = 0xFFFFu;
};
struct FShadingBin
{
uint16 Primary = 0xFFFFu;
};
using PrimitiveRasterBinType = TArray<FRasterBin, TInlineAllocator<1>>;
using PrimitiveShadingBinType = TArray<FShadingBin, TInlineAllocator<1>>;
struct FPrimitiveReferences
{
const FPrimitiveSceneInfo* SceneInfo = nullptr;
PrimitiveRasterBinType RasterBins;
PrimitiveShadingBinType ShadingBins;
bool bWritesCustomDepthStencil = false;
};
using PrimitiveMapType = Experimental::TRobinHoodHashMap<const FPrimitiveSceneInfo*, FPrimitiveReferences>;
public:
FNaniteVisibility();
void BeginVisibilityFrame();
void FinishVisibilityFrame();
/**
* BeginVisibilityQuery and FinishVisibilityQuery are thread safe with respect to each other,
* but not with respect to BeginVisibilityFrame/FinishVisibilityFrame.
**/
FNaniteVisibilityQuery* BeginVisibilityQuery(
FSceneRenderingBulkObjectAllocator& Allocator,
FScene& Scene,
const TConstArrayView<FConvexVolume>& ViewList,
const class FNaniteRasterPipelines* RasterPipelines,
const class FNaniteShadingPipelines* ShadingPipelines,
const UE::Tasks::FTask& PrerequisiteTask = {}
);
PrimitiveRasterBinType* GetRasterBinReferences(const FPrimitiveSceneInfo* SceneInfo);
PrimitiveShadingBinType* GetShadingBinReferences(const FPrimitiveSceneInfo* SceneInfo);
void RemoveReferences(const FPrimitiveSceneInfo* SceneInfo);
private:
FPrimitiveReferences* FindOrAddPrimitiveReferences(const FPrimitiveSceneInfo* SceneInfo);
// Translator should remain valid between Begin/FinishVisibilityFrame. That is, no adding or removing raster bins
FNaniteRasterBinIndexTranslator BinIndexTranslator;
TArray<FNaniteVisibilityQuery*, TInlineAllocator<32>> VisibilityQueries;
TArray<UE::Tasks::FTask, SceneRenderingAllocator> ActiveEvents;
PrimitiveMapType PrimitiveReferences;
UE::FMutex Mutex;
uint8 bCalledBegin : 1;
};
namespace Nanite
{
extern const FNaniteVisibilityResults* GetVisibilityResults(const FNaniteVisibilityQuery* Query);
extern UE::Tasks::FTask GetVisibilityTask(const FNaniteVisibilityQuery* Query);
}
class FNaniteScopedVisibilityFrame
{
public:
FNaniteScopedVisibilityFrame(const bool bInEnabled, FNaniteVisibility& InVisibility)
: Visibility(InVisibility)
, bEnabled(bInEnabled)
{
if (bEnabled)
{
Visibility.BeginVisibilityFrame();
}
}
~FNaniteScopedVisibilityFrame()
{
if (bEnabled)
{
Visibility.FinishVisibilityFrame();
}
}
FORCEINLINE FNaniteVisibility& Get()
{
return Visibility;
}
private:
FNaniteVisibility& Visibility;
bool bEnabled;
};