554 lines
21 KiB
C++
554 lines
21 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "RenderResource.h"
|
|
#include "RendererInterface.h"
|
|
#include "PrimitiveUniformShaderParameters.h"
|
|
#include "PrimitiveSceneInfo.h"
|
|
#include "SpanAllocator.h"
|
|
#include "GrowOnlySpanAllocator.h"
|
|
#include "InstanceCulling/InstanceCullingLoadBalancer.h"
|
|
#include "MeshBatch.h"
|
|
#include "LightSceneData.h"
|
|
#include "SceneUniformBuffer.h"
|
|
#include "UnifiedBuffer.h"
|
|
#include "ScenePrimitiveUpdates.h"
|
|
#include "GPUSceneWriter.h"
|
|
#include "RendererPrivateUtils.h"
|
|
|
|
class FRDGExternalAccessQueue;
|
|
class FRHICommandList;
|
|
class FScene;
|
|
class FViewInfo;
|
|
class FLightSceneInfoCompact;
|
|
class FGPUScene;
|
|
class FGPUSceneDynamicContext;
|
|
class FViewUniformShaderParameters;
|
|
class FInstanceCullingOcclusionQueryRenderer;
|
|
class FScenePreUpdateChangeSet;
|
|
class FScenePostUpdateChangeSet;
|
|
class FPrimitiveSceneProxy;
|
|
struct FLightSceneChangeSet;
|
|
class FGPUSceneWriterParameters;
|
|
|
|
namespace UE::Renderer::Private
|
|
{
|
|
class IShadowInvalidatingInstances;
|
|
}
|
|
|
|
DECLARE_GPU_STAT_NAMED_EXTERN(GPUSceneUpdate, TEXT("GPUSceneUpdate"));
|
|
|
|
#if !ENABLE_SCENE_DATA_DX11_UB_ERROR_WORKAROUND
|
|
// Note: this is declared in GPUSceneWriter.h (a public header) until such a time as the UB path works.
|
|
// Parameter sub struct that is common to all parameter use-cases
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FGPUSceneCommonParameters, RENDERER_API)
|
|
SHADER_PARAMETER(uint32, GPUSceneInstanceDataSOAStride)
|
|
SHADER_PARAMETER(uint32, GPUSceneFrameNumber)
|
|
SHADER_PARAMETER(int32, GPUSceneMaxAllocatedInstanceId)
|
|
SHADER_PARAMETER(int32, GPUSceneMaxPersistentPrimitiveIndex)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
#endif
|
|
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FGPUSceneResourceParameters, RENDERER_API)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FGPUSceneCommonParameters, CommonParameters)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float4>, GPUSceneInstanceSceneData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float4>, GPUSceneInstancePayloadData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float4>, GPUScenePrimitiveSceneData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(StructuredBuffer<float4>, GPUSceneLightmapData)
|
|
SHADER_PARAMETER_RDG_BUFFER_SRV(ByteAddressBuffer, GPUSceneLightData)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
//Non-RDG paramters, untracked, use with care (or preferably, don't)
|
|
BEGIN_SHADER_PARAMETER_STRUCT(FGPUSceneResourceParametersRHI, RENDERER_API)
|
|
SHADER_PARAMETER_STRUCT_INCLUDE(FGPUSceneCommonParameters, CommonParameters)
|
|
SHADER_PARAMETER_SRV(StructuredBuffer<float4>, GPUSceneInstanceSceneData)
|
|
SHADER_PARAMETER_SRV(StructuredBuffer<float4>, GPUSceneInstancePayloadData)
|
|
SHADER_PARAMETER_SRV(StructuredBuffer<float4>, GPUScenePrimitiveSceneData)
|
|
SHADER_PARAMETER_SRV(StructuredBuffer<float4>, GPUSceneLightmapData)
|
|
SHADER_PARAMETER_SRV(ByteAddressBuffer, GPUSceneLightData)
|
|
END_SHADER_PARAMETER_STRUCT()
|
|
|
|
DECLARE_SCENE_UB_STRUCT(FGPUSceneResourceParameters, GPUScene, RENDERER_API)
|
|
|
|
/**
|
|
* Used to manage dynamic primitives for a given view, during InitViews the data is collected and then can be committed to the GPU-Scene.
|
|
* Once committed the range of indices are valid and can be used to calculate the PrimitiveIds.
|
|
*/
|
|
class FGPUScenePrimitiveCollector
|
|
{
|
|
public:
|
|
FGPUScenePrimitiveCollector(FGPUSceneDynamicContext* InGPUSceneDynamicContext = nullptr) :
|
|
GPUSceneDynamicContext(InGPUSceneDynamicContext)
|
|
{};
|
|
|
|
/**
|
|
* Add data for a primitive with a number of instances.
|
|
* May be called outside (before) a FGPUScene::Begin/EndRender block.
|
|
* Note: needs to be virtual to prevent a linker error
|
|
*/
|
|
virtual void Add(
|
|
const FMeshBatchDynamicPrimitiveData* MeshBatchData,
|
|
const FPrimitiveUniformShaderParameters& PrimitiveShaderParams,
|
|
uint32 NumInstances,
|
|
uint32& OutPrimitiveIndex,
|
|
uint32& OutInstanceSceneDataOffset);
|
|
|
|
/**
|
|
* Allocates the range in GPUScene and queues the data for upload.
|
|
* After this is called no more calls to Add are allowed.
|
|
* Only allowed inside a FGPUScene::Begin/EndRender block.
|
|
*/
|
|
RENDERER_API void Commit();
|
|
|
|
/**
|
|
* Get the range of Primitive IDs in GPU-Scene for this batch of dynamic primitives, only valid to call after commit.
|
|
*/
|
|
FORCEINLINE const TRange<int32>& GetPrimitiveIdRange() const
|
|
{
|
|
check(bCommitted || UploadData == nullptr);
|
|
return PrimitiveIdRange;
|
|
}
|
|
|
|
FORCEINLINE int32 GetInstanceSceneDataOffset() const
|
|
{
|
|
check(bCommitted || UploadData == nullptr);
|
|
|
|
return UploadData != nullptr ? UploadData->InstanceSceneDataOffset : 0;
|
|
}
|
|
|
|
FORCEINLINE int32 GetInstancePayloadDataOffset() const
|
|
{
|
|
check(bCommitted || UploadData == nullptr);
|
|
|
|
return UploadData != nullptr ? UploadData->InstancePayloadDataOffset : 0;
|
|
}
|
|
|
|
int32 Num() const { return UploadData != nullptr ? UploadData->PrimitiveData.Num() : 0; }
|
|
int32 NumInstances() const { return UploadData != nullptr ? UploadData->TotalInstanceCount : 0; }
|
|
int32 NumPayloadDataSlots() const { return UploadData != nullptr ? UploadData->InstancePayloadDataFloat4Count : 0; }
|
|
const FPrimitiveUniformShaderParameters* GetPrimitiveShaderParameters(int32 PrimitiveId) const;
|
|
|
|
#if DO_CHECK
|
|
/**
|
|
* Determines if the specified primitive has been sufficiently processed and its data can be read
|
|
*/
|
|
void CheckPrimitiveProcessed(uint32 PrimitiveIndex, const FGPUScene& GPUScene) const;
|
|
#endif // DO_CHECK
|
|
|
|
private:
|
|
|
|
friend class FGPUScene;
|
|
friend class FGPUSceneDynamicContext;
|
|
friend struct FUploadDataSourceAdapterDynamicPrimitives;
|
|
|
|
struct FPrimitiveData
|
|
{
|
|
FMeshBatchDynamicPrimitiveData SourceData;
|
|
const FPrimitiveUniformShaderParameters* ShaderParams = nullptr;
|
|
uint32 NumInstances = 0;
|
|
uint32 LocalInstanceSceneDataOffset = INDEX_NONE;
|
|
uint32 LocalPayloadDataOffset = INDEX_NONE;
|
|
};
|
|
|
|
struct FUploadData
|
|
{
|
|
TArray<FPrimitiveData, TInlineAllocator<8>> PrimitiveData;
|
|
TArray<uint32> GPUWritePrimitives;
|
|
|
|
uint32 InstanceSceneDataOffset = INDEX_NONE;
|
|
uint32 TotalInstanceCount = 0;
|
|
uint32 InstancePayloadDataOffset = INDEX_NONE;
|
|
uint32 InstancePayloadDataFloat4Count = 0;
|
|
bool bIsUploaded = false;
|
|
};
|
|
|
|
FUploadData* AllocateUploadData();
|
|
|
|
/**
|
|
* Range in GPU scene allocated to the dynamic primitives.
|
|
*/
|
|
TRange<int32> PrimitiveIdRange = TRange<int32>::Empty();
|
|
FUploadData* UploadData = nullptr; // Owned by FGPUSceneDynamicContext
|
|
bool bCommitted = false;
|
|
FGPUSceneDynamicContext* GPUSceneDynamicContext = nullptr;
|
|
};
|
|
|
|
// TODO: move to own header
|
|
class FInstanceProcessingGPULoadBalancer;
|
|
|
|
/**
|
|
* Contains and controls the lifetime of any dynamic primitive data collected for the scene rendering.
|
|
* Typically shares life-time with the SceneRenderer.
|
|
*/
|
|
class FGPUSceneDynamicContext
|
|
{
|
|
public:
|
|
FGPUSceneDynamicContext(FGPUScene& InGPUScene) : GPUScene(InGPUScene) {}
|
|
~FGPUSceneDynamicContext();
|
|
|
|
void Release();
|
|
|
|
private:
|
|
friend class FGPUScene;
|
|
friend class FGPUScenePrimitiveCollector;
|
|
|
|
FGPUScenePrimitiveCollector::FUploadData* AllocateDynamicPrimitiveData();
|
|
UE::FMutex DymamicPrimitiveUploadDataMutex;
|
|
TArray<FGPUScenePrimitiveCollector::FUploadData*, TInlineAllocator<128, SceneRenderingAllocator> > DymamicPrimitiveUploadData;
|
|
FGPUScene& GPUScene;
|
|
};
|
|
|
|
struct FGPUSceneInstanceRange
|
|
{
|
|
FGPUSceneInstanceRange(FPersistentPrimitiveIndex InPrimitive, uint32 InInstanceSceneDataOffset, uint32 InNumInstanceSceneDataEntries)
|
|
: Primitive(InPrimitive)
|
|
, InstanceSceneDataOffset(InInstanceSceneDataOffset)
|
|
, NumInstanceSceneDataEntries(InNumInstanceSceneDataEntries)
|
|
{}
|
|
|
|
FPersistentPrimitiveIndex Primitive;
|
|
uint32 InstanceSceneDataOffset;
|
|
uint32 NumInstanceSceneDataEntries;
|
|
};
|
|
|
|
class FGPUScene
|
|
{
|
|
public:
|
|
FGPUScene(FScene &InScene);
|
|
~FGPUScene();
|
|
|
|
using FUpdateFromComputeCommands = FScenePrimitiveUpdates::TPayloadRangeView<FUpdateInstanceFromComputeCommand>;
|
|
|
|
void SetEnabled(ERHIFeatureLevel::Type InFeatureLevel);
|
|
bool IsEnabled() const { return bIsEnabled; }
|
|
/**
|
|
* Call at start of rendering (but after scene primitives are updated) to let GPU-Scene record scene primitive count
|
|
* and prepare for dynamic primitive allocations.
|
|
* Scene may be NULL which means there are zero scene primitives (but there may be dynamic ones added later).
|
|
*/
|
|
void BeginRender(FRDGBuilder& GraphBuilder, FGPUSceneDynamicContext &GPUSceneDynamicContext);
|
|
inline bool IsRendering() const { return bInBeginEndBlock; }
|
|
void EndRender();
|
|
|
|
ERHIFeatureLevel::Type GetFeatureLevel() const { return FeatureLevel; }
|
|
EShaderPlatform GetShaderPlatform() const { return GShaderPlatformForFeatureLevel[FeatureLevel]; }
|
|
|
|
/**
|
|
* Allocates a range of space in the instance scene data buffer for the required number of instances,
|
|
* returns the offset to the first instance or INDEX_NONE if either the allocation failed or NumInstanceSceneDataEntries was zero.
|
|
* Marks the instances as requiring update (actual update is handled later).
|
|
*/
|
|
int32 AllocateInstanceSceneDataSlots(FPersistentPrimitiveIndex PersistentPrimitiveIndex, int32 NumInstanceSceneDataEntries);
|
|
|
|
/**
|
|
* Free the instance data slots for reuse.
|
|
*/
|
|
void FreeInstanceSceneDataSlots(int32 InstanceSceneDataOffset, int32 NumInstanceSceneDataEntries);
|
|
|
|
int32 AllocateInstancePayloadDataSlots(int32 NumInstancePayloadFloat4Entries);
|
|
void FreeInstancePayloadDataSlots(int32 InstancePayloadDataOffset, int32 NumInstancePayloadFloat4Entries);
|
|
|
|
/**
|
|
* Upload primitives from View.DynamicPrimitiveCollector.
|
|
*/
|
|
void UploadDynamicPrimitiveShaderDataForView(FRDGBuilder& GraphBuilder, FViewInfo& View, bool bRayTracing = false, UE::Renderer::Private::IShadowInvalidatingInstances *ShadowInvalidatingInstances = nullptr);
|
|
|
|
/**
|
|
* Modifies the GPUScene specific scene UB parameters to the current versions. Returns true if any of the parameters changed.
|
|
*/
|
|
bool FillSceneUniformBuffer(FRDGBuilder& GraphBuilder, FSceneUniformBuffer& SceneUB) const;
|
|
|
|
/**
|
|
* Pull all pending updates from Scene and upload primitive & instance data.
|
|
*/
|
|
void Update(FRDGBuilder& GraphBuilder, FSceneUniformBuffer& SceneUB, FRDGExternalAccessQueue& ExternalAccessQueue, const FUpdateFromComputeCommands& UpdatesFromCompute, const UE::Tasks::FTask& UpdateTaskPrerequisites = {});
|
|
|
|
/**
|
|
* Queue the given primitive for upload to GPU at next call to Update.
|
|
* May be called multiple times, dirty-flags are cumulative.
|
|
*/
|
|
void RENDERER_API AddPrimitiveToUpdate(FPersistentPrimitiveIndex PersistentPrimitiveIndex, EPrimitiveDirtyState DirtyState = EPrimitiveDirtyState::ChangedAll);
|
|
|
|
FORCEINLINE EPrimitiveDirtyState GetPrimitiveDirtyState(FPersistentPrimitiveIndex PersistentPrimitiveIndex) const
|
|
{
|
|
if (!PrimitiveDirtyState.IsValidIndex(PersistentPrimitiveIndex.Index))
|
|
{
|
|
return EPrimitiveDirtyState::None;
|
|
}
|
|
return PrimitiveDirtyState[PersistentPrimitiveIndex.Index];
|
|
}
|
|
|
|
uint32 GetSceneFrameNumber() const { return SceneFrameNumber; }
|
|
|
|
int32 GetNumInstances() const { return InstanceSceneDataAllocator.GetMaxSize(); }
|
|
int32 GetNumPrimitives() const { return DynamicPrimitivesOffset; }
|
|
int32 GetMaxLightId() const { return NumGPULights; }
|
|
int32 GetNumLightmapDataItems() const { return LightmapDataAllocator.GetMaxSize(); }
|
|
FGPUSceneDynamicContext* GetCurrentDynamicContext() const { return CurrentDynamicContext; }
|
|
/**
|
|
* Returns the highest instance ID that is represented in the GPU scene (which may be lower than the host allocated IDs due to various limits)
|
|
* Never larger than MAX_INSTANCE_ID, see Engine\Shaders\Shared\SceneDefinitions.h
|
|
*/
|
|
uint32 GetInstanceIdUpperBoundGPU() const;
|
|
|
|
const FSpanAllocator& GetInstanceSceneDataAllocator() const { return InstanceSceneDataAllocator; }
|
|
|
|
/**
|
|
* Return the GPU scene resource
|
|
*/
|
|
FGPUSceneResourceParameters GetShaderParameters(FRDGBuilder& GraphBuilder) const;
|
|
|
|
/**
|
|
* Draw GPU-Scene debug info, such as bounding boxes. Call once per view at some point in the frame after GPU scene has been updated fully.
|
|
* What is drawn is controlled by the CVar: r.GPUScene.DebugMode. Enabling this cvar causes ShaderDraw to be being active (if supported).
|
|
*/
|
|
void DebugRender(FRDGBuilder& GraphBuilder, FSceneUniformBuffer& SceneUniformBuffer, FViewInfo& View);
|
|
|
|
/**
|
|
* Manually trigger an allocator consolidate (will otherwise be done when an item is allocated).
|
|
*/
|
|
void ConsolidateInstanceDataAllocations();
|
|
|
|
/**
|
|
* Executes GPUScene writes that were deferred until a later point in scene rendering
|
|
**/
|
|
bool ExecuteDeferredGPUWritePass(FRDGBuilder& GraphBuilder, TArray<FViewInfo>& Views, EGPUSceneGPUWritePass Pass);
|
|
|
|
/** Returns whether or not a GPU Write is pending for the specified primitive */
|
|
bool HasPendingGPUWrite(uint32 PrimitiveId) const;
|
|
|
|
/**
|
|
* Called by FScene::UpdateAllPrimimitiveSceneInfos before the scene is udated.
|
|
*/
|
|
void OnPreSceneUpdate(FRDGBuilder& GraphBuilder, const FScenePreUpdateChangeSet& ScenePreUpdateData);
|
|
|
|
/**
|
|
* Called by FScene::UpdateAllPrimimitiveSceneInfos after the scene is udated.
|
|
*/
|
|
void OnPostSceneUpdate(FRDGBuilder& GraphBuilder, const FScenePostUpdateChangeSet& ScenePostUpdateData);
|
|
|
|
/**
|
|
*/
|
|
void OnPostLightSceneInfoUpdate(FRDGBuilder& OnPostLightSceneInfoUpdate, const FLightSceneChangeSet& LightsPostUpdateData);
|
|
|
|
bool bUpdateAllPrimitives;
|
|
|
|
/** GPU mirror of Primitives */
|
|
TRefCountPtr<FRDGPooledBuffer> PrimitiveBuffer;
|
|
FRDGAsyncScatterUploadBuffer PrimitiveUploadBuffer;
|
|
|
|
/** GPU primitive instance list */
|
|
TRefCountPtr<FRDGPooledBuffer> InstanceSceneDataBuffer;
|
|
FRDGAsyncScatterUploadBuffer InstanceSceneUploadBuffer;
|
|
|
|
FSpanAllocator InstancePayloadDataAllocator;
|
|
TRefCountPtr<FRDGPooledBuffer> InstancePayloadDataBuffer;
|
|
FRDGAsyncScatterUploadBuffer InstancePayloadUploadBuffer;
|
|
|
|
/** GPU light map data */
|
|
FSpanAllocator LightmapDataAllocator;
|
|
TRefCountPtr<FRDGPooledBuffer> LightmapDataBuffer;
|
|
FRDGAsyncScatterUploadBuffer LightmapUploadBuffer;
|
|
|
|
using FInstanceRange = FGPUSceneInstanceRange;
|
|
using FInstanceGPULoadBalancer = TInstanceCullingLoadBalancer<SceneRenderingAllocator>;
|
|
|
|
inline const FScene &GetScene() const { return Scene; }
|
|
|
|
SIZE_T GetAllocatedSize() const;
|
|
|
|
FGPUSceneResourceParametersRHI GetShaderParametersRHI() const;
|
|
|
|
private:
|
|
/**
|
|
* Fills in the FGPUSceneWriterParameters to use for read/write access to the GPU Scene.
|
|
*/
|
|
TRDGUniformBufferRef<FGPUSceneWriterUniformParameters> GetWriteParameters(FRDGBuilder& GraphBuilder, FGPUSceneWriterParameters* LegacyParameters = nullptr);
|
|
|
|
// set to true if the requested (cvar) tile size is >0, otherwise the tile size is re-derived from the instance count
|
|
bool bUseTiledInstanceDataLayout = true;
|
|
|
|
// log2(TileSize) in number of instances, thus the tile-size in memory is #float4s per instance * tilesize
|
|
int32 InstanceDataTileSizeLog2 = -1;
|
|
|
|
uint32 GetInstanceDataTileSizeLog2() const { return InstanceDataTileSizeLog2; }
|
|
uint32 GetInstanceDataTileSize() const { return 1u << InstanceDataTileSizeLog2; }
|
|
uint32 GetInstanceDataTileSizeMask() const;
|
|
uint32 GetInstanceDataTileStride() const;
|
|
|
|
static constexpr int32 InitialBufferSize = 256;
|
|
|
|
TPersistentByteAddressBuffer<FLightSceneData> LightDataBuffer;
|
|
int32 NumGPULights = 0;
|
|
UE::Tasks::FTask LightDataSetupTask;
|
|
|
|
#if DO_CHECK
|
|
TArray<FLightSceneData> LightDataArray;
|
|
#endif
|
|
|
|
FGPUSceneCommonParameters CommonParameters;
|
|
|
|
FGPUSceneCommonParameters GetCommonParameters() const;
|
|
|
|
|
|
// Buffers used by GPU-Scene, since they can be resized during updates AND the render passes must retain the
|
|
// right copy (this is chiefly because the init of shadow views after pre-pass means we need to be able to set
|
|
// up GPU-Scene before pre-pass, but then may discover new primitives etc. As there is no way to know how many
|
|
// dynamic primitives will turn up after Pre-pass, we can't guarantee a resize won't happen).
|
|
struct FRegisteredBuffers
|
|
{
|
|
bool IsValid() const { return PrimitiveBuffer != nullptr; }
|
|
|
|
FRDGBuffer* PrimitiveBuffer = nullptr;
|
|
FRDGBuffer* InstanceSceneDataBuffer = nullptr;
|
|
FRDGBuffer* InstancePayloadDataBuffer = nullptr;
|
|
FRDGBuffer* LightmapDataBuffer = nullptr;
|
|
FRDGBuffer* LightDataBuffer = nullptr;
|
|
};
|
|
|
|
|
|
|
|
FScene &Scene;
|
|
FSpanAllocator InstanceSceneDataAllocator;
|
|
|
|
FORCEINLINE void ResizeDirtyState(int32 NewSizeIn)
|
|
{
|
|
if (IsEnabled() && NewSizeIn > PrimitiveDirtyState.Num())
|
|
{
|
|
const int32 NewSize = Align(NewSizeIn, 64);
|
|
static_assert(static_cast<uint32>(EPrimitiveDirtyState::None) == 0U, "Using AddZeroed to ensure efficent add, requires None == 0");
|
|
PrimitiveDirtyState.AddZeroed(NewSize - PrimitiveDirtyState.Num());
|
|
}
|
|
}
|
|
|
|
/** Indices of primitives that need to be updated in GPU Scene */
|
|
TArray<FPersistentPrimitiveIndex> PrimitivesToUpdate;
|
|
|
|
FRegisteredBuffers CachedRegisteredBuffers;
|
|
|
|
TArray<EPrimitiveDirtyState> PrimitiveDirtyState;
|
|
|
|
TArray<FInstanceRange> InstanceRangesToClear;
|
|
|
|
struct FDeferredGPUWrite
|
|
{
|
|
FGPUSceneWriteDelegateRef DataWriterGPU;
|
|
int32 ViewId = INDEX_NONE;
|
|
uint32 PrimitiveId = INDEX_NONE;
|
|
uint32 InstanceSceneDataOffset = INDEX_NONE;
|
|
uint32 NumCustomDataFloats = INDEX_NONE;
|
|
uint32 PackedInstanceSceneDataFlags = 0u;
|
|
};
|
|
|
|
static constexpr uint32 NumDeferredGPUWritePasses = uint32(EGPUSceneGPUWritePass::Num);
|
|
TArray<FDeferredGPUWrite> DeferredGPUWritePassDelegates[NumDeferredGPUWritePasses];
|
|
EGPUSceneGPUWritePass LastDeferredGPUWritePass = EGPUSceneGPUWritePass::None;
|
|
|
|
TRange<int32> CommitPrimitiveCollector(FGPUScenePrimitiveCollector& PrimitiveCollector);
|
|
|
|
|
|
friend class FGPUScenePrimitiveCollector;
|
|
|
|
/**
|
|
* Stores a copy of the Scene.GetFrameNumber() when updated. Used to track which primitives/instances are updated.
|
|
* When using GPU-Scene for rendering it should ought to be the same as that stored in the Scene (otherwise they are not in sync).
|
|
*/
|
|
uint32 SceneFrameNumber = 0xFFFFFFFF;
|
|
|
|
int32 DynamicPrimitivesOffset = 0;
|
|
|
|
bool bIsEnabled = false;
|
|
bool bInBeginEndBlock = false;
|
|
FGPUSceneDynamicContext* CurrentDynamicContext = nullptr;
|
|
|
|
ERHIFeatureLevel::Type FeatureLevel;
|
|
|
|
FRegisteredBuffers UpdateBufferAllocations(FRDGBuilder& GraphBuilder, FSceneUniformBuffer& SceneUB);
|
|
|
|
/**
|
|
* Register the external buffers with the graphbuilder.
|
|
*/
|
|
FRegisteredBuffers RegisterBuffers(FRDGBuilder& GraphBuilder) const;
|
|
|
|
/**
|
|
* Generalized upload that uses an adapter to abstract the data souce. Enables uploading scene primitives & dynamic primitives using a single path.
|
|
* @parameter Scene may be null, as it is only needed for the Nanite material table update (which is coupled to the Scene at the moment).
|
|
*/
|
|
template<typename FUploadDataSourceAdapter>
|
|
void UploadGeneral(FRDGBuilder& GraphBuilder, const FRegisteredBuffers& BufferState, FRDGExternalAccessQueue* ExternalAccessQueue, const FUploadDataSourceAdapter& UploadDataSourceAdapter, const UE::Tasks::FTask& PrerequisiteTask);
|
|
|
|
/**
|
|
* Upload scene light data to gpu
|
|
*/
|
|
void UpdateGPULights(FRDGBuilder& GraphBuilder, const UE::Tasks::FTask& PrerequisiteTask, const FLightSceneChangeSet& LightsPostUpdateData);
|
|
|
|
static void InitLightData(const FLightSceneInfoCompact& LightInfoCompact, bool bAllowStaticLighting, uint32 LightShaderParameterFlags, FLightSceneData& DataOut);
|
|
|
|
void UploadDynamicPrimitiveShaderDataForViewInternal(FRDGBuilder& GraphBuilder, FViewInfo& View, bool bRayTracing, UE::Renderer::Private::IShadowInvalidatingInstances *ShadowInvalidatingInstances);
|
|
|
|
void UpdateInternal(FRDGBuilder& GraphBuilder, FSceneUniformBuffer& SceneUB, FRDGExternalAccessQueue& ExternalAccessQueue, const UE::Tasks::FTask& UpdateTaskPrerequisites, const FUpdateFromComputeCommands& UpdatesFromCompute);
|
|
|
|
void AddUpdatePrimitiveIdsPass(FRDGBuilder& GraphBuilder, FInstanceGPULoadBalancer& IdOnlyUpdateItems);
|
|
|
|
void AddClearInstancesPass(FRDGBuilder& GraphBuilder, FInstanceCullingOcclusionQueryRenderer* OcclusionQueryRenderer = nullptr);
|
|
|
|
|
|
#if !UE_BUILD_SHIPPING
|
|
FDelegateHandle ScreenMessageDelegate;
|
|
bool bLoggedInstanceOverflow = false;
|
|
uint32 MaxInstancesDuringPrevUpdate = 0;
|
|
bool bLoggedLightOverflow = false;
|
|
int32 MaxLightsDuringPrevUpdate = 0;
|
|
#endif // UE_BUILD_SHIPPING
|
|
|
|
};
|
|
|
|
class FGPUSceneScopeBeginEndHelper
|
|
{
|
|
public:
|
|
FGPUSceneScopeBeginEndHelper(FRDGBuilder& GraphBuilder, FGPUScene& InGPUScene, FGPUSceneDynamicContext &GPUSceneDynamicContext) :
|
|
GPUScene(InGPUScene)
|
|
{
|
|
GPUScene.BeginRender(GraphBuilder, GPUSceneDynamicContext);
|
|
}
|
|
|
|
~FGPUSceneScopeBeginEndHelper()
|
|
{
|
|
GPUScene.EndRender();
|
|
}
|
|
|
|
private:
|
|
FGPUSceneScopeBeginEndHelper() = delete;
|
|
FGPUSceneScopeBeginEndHelper(const FGPUSceneScopeBeginEndHelper&) = delete;
|
|
FGPUScene& GPUScene;
|
|
};
|
|
|
|
struct FBatchedPrimitiveShaderData
|
|
{
|
|
static const uint32 DataStrideInFloat4s = BATCHED_PRIMITIVE_DATA_STRIDE_FLOAT4;
|
|
|
|
TStaticArray<FVector4f, DataStrideInFloat4s> Data;
|
|
|
|
FBatchedPrimitiveShaderData()
|
|
: Data(InPlace, NoInit)
|
|
{
|
|
Setup(GetIdentityPrimitiveParameters());
|
|
}
|
|
|
|
explicit FBatchedPrimitiveShaderData(const FPrimitiveUniformShaderParameters& PrimitiveUniformShaderParameters)
|
|
: Data(InPlace, NoInit)
|
|
{
|
|
Setup(PrimitiveUniformShaderParameters);
|
|
}
|
|
|
|
explicit FBatchedPrimitiveShaderData(const FPrimitiveSceneProxy* Proxy);
|
|
|
|
static void Emplace(FBatchedPrimitiveShaderData* Dest, const FPrimitiveUniformShaderParameters& ShaderParams);
|
|
static void Emplace(FBatchedPrimitiveShaderData* Dest, const FPrimitiveSceneProxy* Proxy);
|
|
|
|
private:
|
|
void Setup(const FPrimitiveUniformShaderParameters& PrimitiveUniformShaderParameters);
|
|
};
|