Files
UnrealEngineUWP/Engine/Source/Developer/MaterialBaking/Private/MaterialRenderItem.h
sebastien lussier ba57adfd4b Edigrating 3 CLs to improve HLOD generation time (faster material baking & mesh merging)
CL 10373564 by danny.couture
Optimize Material Baking (Phase 1)
  - Introduce a mecanism to override the vertex/index buffer allocator used for dynamic meshes
  - Avoid GDynamicMesh non-ticked pools build-up by using our own vertex/index buffer pool during baking
  - Reduce reallocation and incurred soft page faults by reusing a single set of vertex/index buffers big enough for the biggest mesh
  - Preemptively detect if smearing would result in monochrome texture to avoid useless work
  - Shrink smeared monochrome textures during the baking process for huge memory savings
  - Move UV smearing in worker threads to avoid blocking the game thread
  - Required shaders are now built asynchronously
  - Add progress bar for material baking
  - 28m23 [at] 150 GB RAM -> 2m14s [at] 45 GB RAM for 6 channels [at] 512x512 when baking materials on ProxyLOD for DATASET-0008a with DDC empty
#rb Jurre.deBaare, Sebastien.Lussier

CL 10516258 by danny.couture
Optimize Material Baking (Phase 2)
  - Implement pipelining with staging buffers to avoid GPU stalls when reading from render targets
  - Reuse the same prepared FMeshBatch instead of rebuilding it for each draw pass
  - Prepare the RenderItem in advance on other threads to reduce work on the game thread
  - Move the staging surface copy out of the render thread
  - Small vertex and index buffers are not reused to avoid dependency locks when mapping them
  - Fix bug in Canvas Flush_RenderThread found while running HLOD rebuild commandlet on Fortnite
  - Delete old and unused MaterialBakingModule.h from public files
  - 4m44s -> 59s for baking 6 channel [at] 1024x1024 when baking materials on ProxyLOD for DATASET-0008a with shaders already compiled
  - Time spent in Material Baking when rebuilding all HLOD on Apollo_POI_Large_HLOD (Phase 1 + 2 combined)
     - 10m18s -> 2m36s for a first rebuild all in editor with no shaders in DDC (cold)
     - 1m23s   -> 20s for a second rebuild all in editor (warm)
#rb Jeremy.Moore, Sebastien.Lussier

CL 11135986 by sebastien.lussier
Optimized mesh merging
* Added DeletePolygons() & DeleteTriangles methods to FMeshDescription which rely on TSets<> instead of performing costly TArray::AddUnique() calls()
* Parallelized UV generation and avoided duplicate processing of the same mesh+lod pairs
* Optimized FMeshDescriptionOperations::GenerateUniqueUVsForStaticMesh()
* Goes from 100s to 10s in my test case
#rb danny.couture, jeanfrancois.dube, richard.talbotwatkin



#ROBOMERGE-OWNER: sebastien.lussier
#ROBOMERGE-AUTHOR: sebastien.lussier
#ROBOMERGE-SOURCE: CL 11206337 via CL 11206341 via CL 11206346
#ROBOMERGE-BOT: (v643-11205221)

[CL 11206493 by sebastien lussier in Main branch]
2020-02-03 11:08:35 -05:00

90 lines
3.1 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "CanvasTypes.h"
#include "MaterialRenderItemData.h"
#include "DynamicMeshBuilder.h"
class FSceneViewFamily;
class FMaterialRenderProxy;
class FSceneView;
class FRHICommandListImmediate;
struct FMaterialData;
struct FMeshData;
struct FMeshPassProcessorRenderState;
// This will hold onto the resources until not needed anymore.
// Move constructor makes it easier to send the destruction to another thread (render thread).
class FMeshBuilderResources : public FMeshBuilderOneFrameResources
{
public:
FMeshBuilderResources() = default;
FMeshBuilderResources(FMeshBuilderResources&& Other)
{
if (this != &Other)
{
VertexBuffer = Other.VertexBuffer;
IndexBuffer = Other.IndexBuffer;
VertexFactory = Other.VertexFactory;
PrimitiveUniformBuffer = Other.PrimitiveUniformBuffer;
Other.VertexBuffer = nullptr;
Other.IndexBuffer = nullptr;
Other.VertexFactory = nullptr;
Other.PrimitiveUniformBuffer = nullptr;
}
}
void Clear()
{
FMeshBuilderOneFrameResources::~FMeshBuilderOneFrameResources();
VertexBuffer = nullptr;
IndexBuffer = nullptr;
VertexFactory = nullptr;
PrimitiveUniformBuffer = nullptr;
}
};
class FMeshMaterialRenderItem : public FCanvasBaseRenderItem
{
public:
FMeshMaterialRenderItem(const FMaterialData* InMaterialSettings, const FMeshData* InMeshSettings, EMaterialProperty InMaterialProperty, FDynamicMeshBufferAllocator* InDynamicMeshBufferAllocator = nullptr);
virtual ~FMeshMaterialRenderItem();
/** Begin FCanvasBaseRenderItem overrides */
virtual bool Render_RenderThread(FRHICommandListImmediate& RHICmdList, FMeshPassProcessorRenderState& DrawRenderState, const FCanvas* Canvas) final;
virtual bool Render_GameThread(const FCanvas* Canvas, FRenderThreadScope& RenderScope) final;
/** End FCanvasBaseRenderItem overrides */
/** Populate vertices and indices according to available mesh data and otherwise uses simple quad */
void GenerateRenderData();
protected:
/** Enqueues the current material to be rendered */
void QueueMaterial(FRHICommandListImmediate& RHICmdList, FMeshPassProcessorRenderState& DrawRenderState, const FSceneView* View);
/** Helper functions to populate render data using either mesh data or a simple quad */
void PopulateWithQuadData();
void PopulateWithMeshData();
public:
/** Mesh and material settings to use while baking out the material */
const FMeshData* MeshSettings;
const FMaterialData* MaterialSettings;
/** Material property to bake out */
EMaterialProperty MaterialProperty;
/** Material render proxy (material/shader) to use while baking */
FMaterialRenderProxy* MaterialRenderProxy;
/** Vertex and index data representing the mesh or a quad */
TArray<FDynamicMeshVertex> Vertices;
TArray<uint32> Indices;
/** Light cache interface object to simulate lightmap behavior in case the material used prebaked ambient occlusion */
FLightCacheInterface* LCI;
/** View family to use while baking */
FSceneViewFamily* ViewFamily;
private:
FMeshBatch MeshElement;
bool bMeshElementDirty;
FMeshBuilderResources MeshBuilderResources;
FDynamicMeshBufferAllocator* DynamicMeshBufferAllocator;
};