Files
UnrealEngineUWP/Engine/Source/Runtime/GeometryCache/Private/GeometryCacheSceneProxy.cpp
Gil Gribb 2e5b4cbbd1 Copying //UE4/Dev-Rendering to Dev-Main (//UE4/Dev-Main)
#lockdown nick.penwarden

==========================
MAJOR FEATURES + CHANGES
==========================

Change 2821445 on 2016/01/08 by Olaf.Piesche
	More vertex factory improvements, storing off particle vertex factories on the scene proxy instead of the dynamic data to avoid recreating all the time; saves up to 2ms render thread time according to QA's testing.

	#rb martin.mittring

Change 2821520 on 2016/01/08 by Olaf.Piesche

	Coloring subuv modules green for easier visual ID

	#rb martin.mittring

Change 2823479 on 2016/01/11 by Chris.Bunner

	Updated Lightmass HLOD logic to avoid HLODs shadowing non-related meshes. Duplicated CL#2823104 from Dev-General.

Change 2823570 on 2016/01/11 by Zabir.Hoque

	Introduce multiplier that controls decal fade speed.

	#CodeReview: Martin.Mittring
	#1777

Change 2823615 on 2016/01/11 by Uriel.Doyon

	Fixed stencil ref multithreading issue.
	Fixed state caching when depth range is enabled.
	#jira UE-24564
	#review marcus.wassmer

Change 2823652 on 2016/01/11 by Zabir.Hoque

	Rename FadeSpeedScale -> FadeDurationScale to be logically more consistent.

	#CodeReview: Martin.Mittring

Change 2824065 on 2016/01/11 by Brian.Karis

	Fixed last viewrect motion blur bug. Enabled new motion blur algorithm for default.

Change 2825432 on 2016/01/12 by Zabir.Hoque

	Store off view matrices at at time of freezing and base lod selection useing relevant matrices, thus allows lods to be frozen. #OR-10918

	#CodeReview: Marcus.Wassmer, Rolando.Caloca, Martin.Mittring

Change 2825971 on 2016/01/12 by Brian.Karis

	New motion blur enabled.

Change 2825974 on 2016/01/12 by Brian.Karis

	Fixed refraction check value. 1 does nothing not 0.

Change 2825975 on 2016/01/12 by Brian.Karis

	Cloth gets skylight for movable sky.

Change 2827519 on 2016/01/13 by Zabir.Hoque

	ALLOW_UAV_CONDITION did not have a safe fallback when not SM5.0 && COMPILER_SUPPORTS_ATTRIBUTES.

	#CodeReview Martin.Mittring, Rolando.Caloca

Change 2830172 on 2016/01/15 by Rolando.Caloca

	DR - Minor cleanup
	- Renamed Vertex Factories' struct Data to struct FData
	- Removed Data type on FVertexFactory

Change 2830242 on 2016/01/15 by Rolando.Caloca

	DR - Prep cleanup for gpu morph targets
	- Split common code for  GPU skin cache into a base class
	- Moved some local static arrays from UpdateMorphVertexBuffer() to static members
	#codereview Lina.Halper

Change 2830455 on 2016/01/15 by Rolando.Caloca

	DR - Compile fix from bad merge
	#jira UE-25557

Change 2832023 on 2016/01/18 by Rolando.Caloca

	DR - Removed TangentZDelta_DEPRECATED from FVertexAnimDelta
	#rb Marcus.Wassmer
	#codereview Lina.Halper

Change 2832067 on 2016/01/18 by Gil.Gribb

	UE4 - Changed PC to default to parallel rendering when not in editor. Fixed lack of a stall on texture locks and unlocks coming from texture streamer. Fixed a few cases where stuff was being added to rhicommandlists even when we were bypassed.

Change 2834379 on 2016/01/19 by Gil.Gribb

	UE4 - fix perf regression related to cvar

Change 2834864 on 2016/01/19 by Olaf.Piesche

	Fixing potential crash with auto-kill trail emitters, fixing use of the wrong flag to auto-deactivate

	#codereview gil.gribb

Change 2835777 on 2016/01/20 by David.Hill

	EyeAdaptation - using a screen center focus in the weights
	#rb Martin Mitring

	related to: UE-15509.  This is adding the ability to focus the basic eye-adaptation region in the center of the screen, and cvar functionality for paragon testing on ps4

Change 2835778 on 2016/01/20 by David.Hill

	EyeAdapation - DefaultFeature for method
	#rb Martin.Mitring
	Adding a default feature cvar for eye adaptation method

Change 2837410 on 2016/01/20 by David.Hill

	OR-13213   SetupPerObjectProjection()
	#test:PC
	#rb:Martin.Mitring
	#codereview:Daniel.Wright

[CL 2845257 by Gil Gribb in Main branch]
2016-01-27 07:18:43 -05:00

345 lines
11 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
#include "GeometryCacheModulePrivatePCH.h"
#include "GeometryCacheSceneProxy.h"
#include "GeometryCacheComponent.h"
#include "GeometryCacheMeshData.h"
FGeometryCacheSceneProxy::FGeometryCacheSceneProxy(UGeometryCacheComponent* Component) : FPrimitiveSceneProxy(Component)
, MaterialRelevance(Component->GetMaterialRelevance(GetScene().GetFeatureLevel()))
{
// Copy each section
const int32 NumSections = Component->TrackSections.Num();
Sections.AddZeroed(NumSections);
for (int SectionIdx = 0; SectionIdx < NumSections; SectionIdx++)
{
FTrackRenderData& SrcSection = Component->TrackSections[SectionIdx];
if (SrcSection.MeshData->Indices.Num() > 0)
{
FGeomCacheTrackProxy* NewSection = new FGeomCacheTrackProxy();
NewSection->WorldMatrix = SrcSection.WorldMatrix;
FGeometryCacheMeshData* MeshData = NewSection->MeshData = SrcSection.MeshData;
// Copy data from vertex buffer
const int32 NumVerts = MeshData->Vertices.Num();
// Allocate verts
NewSection->VertexBuffer.Vertices.Empty(NumVerts);
// Copy verts
NewSection->VertexBuffer.Vertices.Append(MeshData->Vertices);
// Copy index buffer
NewSection->IndexBuffer.Indices = SrcSection.MeshData->Indices;
// Init vertex factory
NewSection->VertexFactory.Init(&NewSection->VertexBuffer);
// Enqueue initialization of render resource
BeginInitResource(&NewSection->VertexBuffer);
BeginInitResource(&NewSection->IndexBuffer);
BeginInitResource(&NewSection->VertexFactory);
// Grab materials
for (FGeometryCacheMeshBatchInfo& BatchInfo : MeshData->BatchesInfo)
{
UMaterialInterface* Material = Component->GetMaterial(BatchInfo.MaterialIndex);
if (Material == nullptr)
{
Material = UMaterial::GetDefaultMaterial(MD_Surface);
}
NewSection->Materials.Push(Material);
}
// Save ref to new section
Sections[SectionIdx] = NewSection;
}
}
}
FGeometryCacheSceneProxy::~FGeometryCacheSceneProxy()
{
for (FGeomCacheTrackProxy* Section : Sections)
{
if (Section != nullptr)
{
Section->VertexBuffer.ReleaseResource();
Section->IndexBuffer.ReleaseResource();
Section->VertexFactory.ReleaseResource();
delete Section;
}
}
Sections.Empty();
}
void FGeometryCacheSceneProxy::GetDynamicMeshElements(const TArray<const FSceneView*>& Views, const FSceneViewFamily& ViewFamily, uint32 VisibilityMap, FMeshElementCollector& Collector) const
{
SCOPE_CYCLE_COUNTER(STAT_GeometryCacheSceneProxy_GetMeshElements);
// Set up wireframe material (if needed)
const bool bWireframe = AllowDebugViewmodes() && ViewFamily.EngineShowFlags.Wireframe;
FColoredMaterialRenderProxy* WireframeMaterialInstance = nullptr;
if (bWireframe)
{
WireframeMaterialInstance = new FColoredMaterialRenderProxy(
GEngine->WireframeMaterial ? GEngine->WireframeMaterial->GetRenderProxy(IsSelected()) : nullptr,
FLinearColor(0, 0.5f, 1.f)
);
Collector.RegisterOneFrameMaterialProxy(WireframeMaterialInstance);
}
// Iterate over sections
for (const FGeomCacheTrackProxy* TrackProxy : Sections )
{
// Render out stored TrackProxy's
if (TrackProxy != nullptr)
{
INC_DWORD_STAT_BY(STAT_GeometryCacheSceneProxy_MeshBatchCount, TrackProxy->MeshData->BatchesInfo.Num());
int32 BatchIndex = 0;
for (FGeometryCacheMeshBatchInfo& BatchInfo : TrackProxy->MeshData->BatchesInfo)
{
FMaterialRenderProxy* MaterialProxy = bWireframe ? WireframeMaterialInstance : TrackProxy->Materials[BatchIndex]->GetRenderProxy(IsSelected());
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
const FSceneView* View = Views[ViewIndex];
// Draw the mesh.
FMeshBatch& Mesh = Collector.AllocateMesh();
FMeshBatchElement& BatchElement = Mesh.Elements[0];
BatchElement.IndexBuffer = &TrackProxy->IndexBuffer;
Mesh.bWireframe = bWireframe;
Mesh.VertexFactory = &TrackProxy->VertexFactory;
Mesh.MaterialRenderProxy = MaterialProxy;
BatchElement.PrimitiveUniformBuffer = CreatePrimitiveUniformBufferImmediate(TrackProxy->WorldMatrix * GetLocalToWorld(), GetBounds(), GetLocalBounds(), true, UseEditorDepthTest());
BatchElement.FirstIndex = BatchInfo.StartIndex;
BatchElement.NumPrimitives = BatchInfo.NumTriangles;
BatchElement.MinVertexIndex = 0;
BatchElement.MaxVertexIndex = TrackProxy->VertexBuffer.Vertices.Num() - 1;
Mesh.ReverseCulling = IsLocalToWorldDeterminantNegative();
Mesh.Type = PT_TriangleList;
Mesh.DepthPriorityGroup = SDPG_World;
Mesh.bCanApplyViewModeOverrides = false;
Collector.AddMesh(ViewIndex, Mesh);
INC_DWORD_STAT_BY(STAT_GeometryCacheSceneProxy_TriangleCount, BatchElement.NumPrimitives);
}
}
++BatchIndex;
}
}
}
// Draw bounds
#if !(UE_BUILD_SHIPPING || UE_BUILD_TEST)
for (int32 ViewIndex = 0; ViewIndex < Views.Num(); ViewIndex++)
{
if (VisibilityMap & (1 << ViewIndex))
{
// Render bounds
RenderBounds(Collector.GetPDI(ViewIndex), ViewFamily.EngineShowFlags, GetBounds(), IsSelected());
}
}
#endif
}
FPrimitiveViewRelevance FGeometryCacheSceneProxy::GetViewRelevance(const FSceneView* View) const
{
FPrimitiveViewRelevance Result;
Result.bDrawRelevance = IsShown(View);
Result.bShadowRelevance = IsShadowCast(View);
Result.bDynamicRelevance = true;
MaterialRelevance.SetPrimitiveViewRelevance(Result);
return Result;
}
bool FGeometryCacheSceneProxy::CanBeOccluded() const
{
return !MaterialRelevance.bDisableDepthTest;
}
uint32 FGeometryCacheSceneProxy::GetMemoryFootprint(void) const
{
return(sizeof(*this) + GetAllocatedSize());
}
uint32 FGeometryCacheSceneProxy::GetAllocatedSize(void) const
{
return(FPrimitiveSceneProxy::GetAllocatedSize());
}
void FGeometryCacheSceneProxy::UpdateSectionWorldMatrix(const int32 SectionIndex, const FMatrix& WorldMatrix)
{
check(SectionIndex < Sections.Num() && "Section Index out of range");
Sections[SectionIndex]->WorldMatrix = WorldMatrix;
}
void FGeometryCacheSceneProxy::UpdateSectionVertexBuffer(const int32 SectionIndex, FGeometryCacheMeshData* MeshData)
{
check(SectionIndex < Sections.Num() && "Section Index out of range");
check(IsInRenderingThread());
Sections[SectionIndex]->MeshData = MeshData;
const bool bRecreate = Sections[SectionIndex]->VertexBuffer.Vertices.Num() != Sections[SectionIndex]->MeshData->Vertices.Num();
Sections[SectionIndex]->VertexBuffer.Vertices.Empty(Sections[SectionIndex]->MeshData->Vertices.Num());
Sections[SectionIndex]->VertexBuffer.Vertices.Append(Sections[SectionIndex]->MeshData->Vertices);
if (bRecreate)
{
Sections[SectionIndex]->VertexBuffer.InitRHI();
}
else
{
Sections[SectionIndex]->VertexBuffer.UpdateRHI();
}
}
void FGeometryCacheSceneProxy::UpdateSectionIndexBuffer(const int32 SectionIndex, const TArray<uint32>& Indices)
{
check(SectionIndex < Sections.Num() && "Section Index out of range");
check(IsInRenderingThread());
const bool bRecreate = Sections[SectionIndex]->IndexBuffer.Indices.Num() != Indices.Num();
Sections[SectionIndex]->IndexBuffer.Indices.Empty(Indices.Num());
Sections[SectionIndex]->IndexBuffer.Indices.Append(Indices);
if (bRecreate)
{
Sections[SectionIndex]->IndexBuffer.InitRHI();
}
else
{
Sections[SectionIndex]->IndexBuffer.UpdateRHI();
}
}
void FGeometryCacheSceneProxy::ClearSections()
{
Sections.Empty();
}
FGeomCacheVertexFactory::FGeomCacheVertexFactory()
{
}
void FGeomCacheVertexFactory::Init_RenderThread(const FGeomCacheVertexBuffer* VertexBuffer)
{
check(IsInRenderingThread());
// Initialize the vertex factory's stream components.
FDataType NewData;
NewData.PositionComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, Position, VET_Float3);
NewData.TextureCoordinates.Add(
FVertexStreamComponent(VertexBuffer, STRUCT_OFFSET(FDynamicMeshVertex, TextureCoordinate), sizeof(FDynamicMeshVertex), VET_Float2)
);
NewData.TangentBasisComponents[0] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentX, VET_PackedNormal);
NewData.TangentBasisComponents[1] = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, TangentZ, VET_PackedNormal);
NewData.ColorComponent = STRUCTMEMBER_VERTEXSTREAMCOMPONENT(VertexBuffer, FDynamicMeshVertex, Color, VET_Color);
SetData(NewData);
}
void FGeomCacheVertexFactory::Init(const FGeomCacheVertexBuffer* VertexBuffer)
{
if (IsInRenderingThread())
{
Init_RenderThread(VertexBuffer);
}
else
{
ENQUEUE_UNIQUE_RENDER_COMMAND_TWOPARAMETER(
InitGeomCacheVertexFactory,
FGeomCacheVertexFactory*, VertexFactory, this,
const FGeomCacheVertexBuffer*, VertexBuffer, VertexBuffer,
{
VertexFactory->Init_RenderThread(VertexBuffer);
});
}
}
void FGeomCacheIndexBuffer::InitRHI()
{
FRHIResourceCreateInfo CreateInfo;
void* Buffer = nullptr;
IndexBufferRHI = RHICreateAndLockIndexBuffer(sizeof(uint32), Indices.Num() * sizeof(uint32), BUF_Static, CreateInfo, Buffer);
// Write the indices to the index buffer.
// Write the indices to the index buffer.
FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(uint32));
RHIUnlockIndexBuffer(IndexBufferRHI);
}
void FGeomCacheIndexBuffer::UpdateRHI()
{
// Copy the index data into the index buffer.
void* Buffer = RHILockIndexBuffer(IndexBufferRHI, 0, Indices.Num() * sizeof(uint32), RLM_WriteOnly);
FMemory::Memcpy(Buffer, Indices.GetData(), Indices.Num() * sizeof(uint32));
RHIUnlockIndexBuffer(IndexBufferRHI);
}
void FGeomCacheVertexBuffer::InitRHI()
{
const uint32 SizeInBytes = Vertices.Num() * sizeof(FDynamicMeshVertex);
FGeomCacheVertexResourceArray ResourceArray(Vertices.GetData(), SizeInBytes);
FRHIResourceCreateInfo CreateInfo(&ResourceArray);
VertexBufferRHI = RHICreateVertexBuffer(SizeInBytes, BUF_Static, CreateInfo);
}
void FGeomCacheVertexBuffer::UpdateRHI()
{
// Copy the vertex data into the vertex buffer.
void* VertexBufferData = RHILockVertexBuffer(VertexBufferRHI, 0, Vertices.Num() * sizeof(FDynamicMeshVertex), RLM_WriteOnly);
FMemory::Memcpy(VertexBufferData, Vertices.GetData(), Vertices.Num() * sizeof(FDynamicMeshVertex));
RHIUnlockVertexBuffer(VertexBufferRHI);
}
FGeomCacheVertexResourceArray::FGeomCacheVertexResourceArray(void* InData, uint32 InSize) : Data(InData)
, Size(InSize)
{
}
const void* FGeomCacheVertexResourceArray::GetResourceData() const
{
return Data;
}
uint32 FGeomCacheVertexResourceArray::GetResourceDataSize() const
{
return Size;
}
void FGeomCacheVertexResourceArray::Discard()
{
}
bool FGeomCacheVertexResourceArray::IsStatic() const
{
return false;
}
bool FGeomCacheVertexResourceArray::GetAllowCPUAccess() const
{
return false;
}
void FGeomCacheVertexResourceArray::SetAllowCPUAccess(bool bInNeedsCPUAccess)
{
}