You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
Run a compute job that packs most commonly used instance data (LocalToWorld matrix and some other bits - 80 bytes) into per-instance vertex buffer. Vertex shader does not have access to GPUScene and instead loads instance data from a per-instance vertex buffer. If it needs more primitive/instance data than available then it will load it from Primitive UB, binding unique uniform buffer and breaking auto-instancing. Pixel shader has a full access to a GPUScene There are 3 ways how FSceneDataIntermediates gets populated 1. PrimitiveId + GPUScene (Desktop) 2. Per-Instance data + Primitive UB (Mobile) 3. Primitive UB (auto-instancing disabled) Details for GPUScene specific vertex inputs and access to FSceneDataIntermediates are hidden behind a macro: VF_GPUSCENE_DECLARE_INPUT_BLOCK VF_GPUSCENE_GET_INTERMEDIATES FSceneDataIntermediates is now stored in FVertexFactoryIntermediates, FMaterialVertexParameters. Added a few GetPrimitiveData() overloads that allows you to access PrimitiveData depending on current context. Removed most of the cases where GetPrimitiveData() gets used with PrimitiveId. #rb Ola.Ollson [CL 17093848 by Dmitriy Dyomin in ue5-main branch]
238 lines
7.6 KiB
C++
238 lines
7.6 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
/*=============================================================================
|
|
MeshDrawCommands.h: Mesh draw commands.
|
|
=============================================================================*/
|
|
|
|
#pragma once
|
|
|
|
#include "MeshPassProcessor.h"
|
|
#include "TranslucencyPass.h"
|
|
#include "InstanceCulling/InstanceCullingContext.h"
|
|
#include "InstanceCulling/InstanceCullingManager.h"
|
|
|
|
struct FMeshBatchAndRelevance;
|
|
class FStaticMeshBatch;
|
|
class FParallelCommandListSet;
|
|
class FInstanceCullingManager;
|
|
|
|
/**
|
|
* Global vertex buffer pool used for GPUScene primitive id arrays.
|
|
*/
|
|
|
|
struct FPrimitiveIdVertexBufferPoolEntry
|
|
{
|
|
int32 BufferSize = 0;
|
|
uint32 LastDiscardId = 0;
|
|
FBufferRHIRef BufferRHI;
|
|
};
|
|
|
|
class FPrimitiveIdVertexBufferPool : public FRenderResource
|
|
{
|
|
public:
|
|
FPrimitiveIdVertexBufferPool();
|
|
~FPrimitiveIdVertexBufferPool();
|
|
|
|
FPrimitiveIdVertexBufferPoolEntry Allocate(int32 BufferSize);
|
|
void ReturnToFreeList(FPrimitiveIdVertexBufferPoolEntry Entry);
|
|
RENDERER_API void DiscardAll();
|
|
|
|
virtual void ReleaseDynamicRHI() override;
|
|
|
|
private:
|
|
uint32 DiscardId;
|
|
TArray<FPrimitiveIdVertexBufferPoolEntry> Entries;
|
|
FCriticalSection AllocationCS;
|
|
};
|
|
|
|
extern RENDERER_API TGlobalResource<FPrimitiveIdVertexBufferPool> GPrimitiveIdVertexBufferPool;
|
|
|
|
/**
|
|
* Parallel mesh draw command pass setup task context.
|
|
*/
|
|
class FMeshDrawCommandPassSetupTaskContext
|
|
{
|
|
public:
|
|
FMeshDrawCommandPassSetupTaskContext()
|
|
: View(nullptr)
|
|
, Scene(nullptr)
|
|
, ShadingPath(EShadingPath::Num)
|
|
, PassType(EMeshPass::Num)
|
|
, bUseGPUScene(false)
|
|
, bDynamicInstancing(false)
|
|
, bReverseCulling(false)
|
|
, bRenderSceneTwoSided(false)
|
|
, BasePassDepthStencilAccess(FExclusiveDepthStencil::DepthNop_StencilNop)
|
|
, MeshPassProcessor(nullptr)
|
|
, MobileBasePassCSMMeshPassProcessor(nullptr)
|
|
, DynamicMeshElements(nullptr)
|
|
, InstanceFactor(1)
|
|
, NumDynamicMeshElements(0)
|
|
, NumDynamicMeshCommandBuildRequestElements(0)
|
|
, NeedsShaderInitialisation(false)
|
|
, PrimitiveIdBufferData(nullptr)
|
|
, PrimitiveIdBufferDataSize(0)
|
|
, PrimitiveBounds(nullptr)
|
|
, VisibleMeshDrawCommandsNum(0)
|
|
, NewPassVisibleMeshDrawCommandsNum(0)
|
|
, MaxInstances(1)
|
|
{
|
|
}
|
|
|
|
const FViewInfo* View;
|
|
const FScene* Scene;
|
|
EShadingPath ShadingPath;
|
|
EShaderPlatform ShaderPlatform;
|
|
EMeshPass::Type PassType;
|
|
bool bUseGPUScene;
|
|
bool bDynamicInstancing;
|
|
bool bReverseCulling;
|
|
bool bRenderSceneTwoSided;
|
|
FExclusiveDepthStencil::Type BasePassDepthStencilAccess;
|
|
FExclusiveDepthStencil::Type DefaultBasePassDepthStencilAccess;
|
|
|
|
// Mesh pass processor.
|
|
FMeshPassProcessor* MeshPassProcessor;
|
|
FMeshPassProcessor* MobileBasePassCSMMeshPassProcessor;
|
|
const TArray<FMeshBatchAndRelevance, SceneRenderingAllocator>* DynamicMeshElements;
|
|
const TArray<FMeshPassMask, SceneRenderingAllocator>* DynamicMeshElementsPassRelevance;
|
|
|
|
// Commands.
|
|
int32 InstanceFactor;
|
|
int32 NumDynamicMeshElements;
|
|
int32 NumDynamicMeshCommandBuildRequestElements;
|
|
FMeshCommandOneFrameArray MeshDrawCommands;
|
|
FMeshCommandOneFrameArray MobileBasePassCSMMeshDrawCommands;
|
|
TArray<const FStaticMeshBatch*, SceneRenderingAllocator> DynamicMeshCommandBuildRequests;
|
|
TArray<const FStaticMeshBatch*, SceneRenderingAllocator> MobileBasePassCSMDynamicMeshCommandBuildRequests;
|
|
FDynamicMeshDrawCommandStorage MeshDrawCommandStorage;
|
|
FGraphicsMinimalPipelineStateSet MinimalPipelineStatePassSet;
|
|
bool NeedsShaderInitialisation;
|
|
|
|
// Resources preallocated on rendering thread.
|
|
void* PrimitiveIdBufferData;
|
|
int32 PrimitiveIdBufferDataSize;
|
|
FMeshCommandOneFrameArray TempVisibleMeshDrawCommands;
|
|
|
|
// For UpdateTranslucentMeshSortKeys.
|
|
ETranslucencyPass::Type TranslucencyPass;
|
|
ETranslucentSortPolicy::Type TranslucentSortPolicy;
|
|
FVector TranslucentSortAxis;
|
|
FVector ViewOrigin;
|
|
FMatrix ViewMatrix;
|
|
const TArray<struct FPrimitiveBounds>* PrimitiveBounds;
|
|
|
|
// For logging instancing stats.
|
|
int32 VisibleMeshDrawCommandsNum;
|
|
int32 NewPassVisibleMeshDrawCommandsNum;
|
|
int32 MaxInstances;
|
|
|
|
FInstanceCullingContext InstanceCullingContext;
|
|
FInstanceCullingResult InstanceCullingResult;
|
|
};
|
|
|
|
/**
|
|
* Parallel mesh draw command processing and rendering.
|
|
* Encapsulates two parallel tasks - mesh command setup task and drawing task.
|
|
*/
|
|
class FParallelMeshDrawCommandPass
|
|
{
|
|
public:
|
|
enum class EWaitThread
|
|
{
|
|
Render,
|
|
Task,
|
|
TaskAlreadyWaited,
|
|
};
|
|
|
|
FParallelMeshDrawCommandPass()
|
|
: bHasInstanceCullingDrawParameters(false)
|
|
, MaxNumDraws(0)
|
|
{
|
|
}
|
|
|
|
~FParallelMeshDrawCommandPass();
|
|
|
|
/**
|
|
* Dispatch visible mesh draw command process task, which prepares this pass for drawing.
|
|
* This includes generation of dynamic mesh draw commands, draw sorting and draw merging.
|
|
*/
|
|
void DispatchPassSetup(
|
|
FScene* Scene,
|
|
const FViewInfo& View,
|
|
FInstanceCullingContext &&InstanceCullingContext,
|
|
EMeshPass::Type PassType,
|
|
FExclusiveDepthStencil::Type BasePassDepthStencilAccess,
|
|
FMeshPassProcessor* MeshPassProcessor,
|
|
const TArray<FMeshBatchAndRelevance, SceneRenderingAllocator>& DynamicMeshElements,
|
|
const TArray<FMeshPassMask, SceneRenderingAllocator>* DynamicMeshElementsPassRelevance,
|
|
int32 NumDynamicMeshElements,
|
|
TArray<const FStaticMeshBatch*, SceneRenderingAllocator>& InOutDynamicMeshCommandBuildRequests,
|
|
int32 NumDynamicMeshCommandBuildRequestElements,
|
|
FMeshCommandOneFrameArray& InOutMeshDrawCommands,
|
|
FMeshPassProcessor* MobileBasePassCSMMeshPassProcessor = nullptr, // Required only for the mobile base pass.
|
|
FMeshCommandOneFrameArray* InOutMobileBasePassCSMMeshDrawCommands = nullptr // Required only for the mobile base pass.
|
|
);
|
|
|
|
/**
|
|
* Sync with setup task and run post-instance culling job to create the render commands and instance ID lists and optionally vertex instance data.
|
|
* Needs to happen after DispatchPassSetup and before DispatchDraw, but not before global instance culling has been done.
|
|
*/
|
|
void BuildRenderingCommands(
|
|
FRDGBuilder& GraphBuilder,
|
|
const FGPUScene& GPUScene,
|
|
FInstanceCullingDrawParams& OutInstanceCullingDrawParams);
|
|
|
|
/**
|
|
* Sync with setup task.
|
|
*/
|
|
void WaitForSetupTask();
|
|
|
|
/**
|
|
* Dispatch visible mesh draw command draw task.
|
|
*/
|
|
void DispatchDraw(FParallelCommandListSet* ParallelCommandListSet, FRHICommandList& RHICmdList, const FInstanceCullingDrawParams* InstanceCullingDrawParams = nullptr) const;
|
|
|
|
void WaitForTasksAndEmpty(EWaitThread WaitThread = EWaitThread::Render);
|
|
void SetDumpInstancingStats(const FString& InPassName);
|
|
bool HasAnyDraw() const { return MaxNumDraws > 0; }
|
|
|
|
void InitCreateSnapshot()
|
|
{
|
|
new (&TaskContext.MinimalPipelineStatePassSet) FGraphicsMinimalPipelineStateSet();
|
|
}
|
|
|
|
void FreeCreateSnapshot()
|
|
{
|
|
TaskContext.MinimalPipelineStatePassSet.~FGraphicsMinimalPipelineStateSet();
|
|
}
|
|
|
|
static bool IsOnDemandShaderCreationEnabled();
|
|
|
|
FInstanceCullingContext* GetInstanceCullingContext() { return &TaskContext.InstanceCullingContext; }
|
|
const FGraphEventRef& GetTaskEvent() const { return TaskEventRef; }
|
|
|
|
private:
|
|
FPrimitiveIdVertexBufferPoolEntry PrimitiveIdVertexBufferPoolEntry;
|
|
FMeshDrawCommandPassSetupTaskContext TaskContext;
|
|
FGraphEventRef TaskEventRef;
|
|
FString PassNameForStats;
|
|
|
|
bool bHasInstanceCullingDrawParameters;
|
|
|
|
// Maximum number of draws for this pass. Used to prealocate resources on rendering thread.
|
|
// Has a guarantee that if there won't be any draws, then MaxNumDraws = 0;
|
|
int32 MaxNumDraws;
|
|
|
|
void DumpInstancingStats() const;
|
|
void WaitForMeshPassSetupTask(EWaitThread WaitThread = EWaitThread::Render) const;
|
|
};
|
|
|
|
RENDERER_API extern void SortAndMergeDynamicPassMeshDrawCommands(
|
|
const FSceneView& SceneView,
|
|
FMeshCommandOneFrameArray& VisibleMeshDrawCommands,
|
|
FDynamicMeshDrawCommandStorage& MeshDrawCommandStorage,
|
|
FRHIBuffer*& OutPrimitiveIdVertexBuffer,
|
|
uint32 InstanceFactor,
|
|
const FGPUScenePrimitiveCollector* DynamicPrimitiveCollector);
|