Skip to content

Commit

Permalink
Complete the Cluster rendering version
Browse files Browse the repository at this point in the history
  • Loading branch information
fakersaber committed Dec 7, 2020
1 parent 060a640 commit 28fe0d2
Show file tree
Hide file tree
Showing 7 changed files with 197 additions and 150 deletions.
151 changes: 83 additions & 68 deletions Engine/Shaders/Private/LandscapeVertexFactory.ush

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Engine/Source/Runtime/Landscape/Private/Landscape.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,8 @@ void ULandscapeComponent::CheckGenerateLandscapePlatformData(bool bIsCooking, co

bool bRegenerateVertexData = bMissingVertexData || bMissingPixelData || bHashMismatch;

UE_LOG(LogTemp, Log, TEXT("bRegenerateVertexData: %d, bMissingVertexData: %d, bMissingPixelData: %d, bHashMismatch: %d "), bRegenerateVertexData, bMissingVertexData, bMissingPixelData, bHashMismatch);

if (bRegenerateVertexData)
{
if (bIsCooking)
Expand Down
7 changes: 6 additions & 1 deletion Engine/Source/Runtime/Landscape/Private/LandscapeEdit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6613,9 +6613,9 @@ void ULandscapeComponent::GeneratePlatformVertexData(const ITargetPlatform* Targ
//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
//����ALandscapeSceneProxy Cache
{
uint32 NumComponents = GetLandscapeProxy()->LandscapeComponents.Num();
if (CVarMobileAllowLandScapeInstance.GetValueOnAnyThread() != 0) {

uint32 NumComponents = GetLandscapeProxy()->LandscapeComponents.Num();
check(FMath::IsPowerOfTwo(NumComponents));
uint32 SqrtSize = FMath::Sqrt(NumComponents);
FIntPoint ComponentTotalSize = FIntPoint(SqrtSize, SqrtSize);
Expand All @@ -6626,6 +6626,9 @@ void ULandscapeComponent::GeneratePlatformVertexData(const ITargetPlatform* Targ

const auto& LandscapeGuid = GetLandscapeProxy()->GetLandscapeGuid();
auto BoundsArrayPtr = FLandscapeRenderSystem::LandscapeSystemClusterLocalBounds.Find(LandscapeGuid);

UE_LOG(LogTemp, Log, TEXT("Create LocalBoundData, %u-%u-%u-%u"), LandscapeGuid.A, LandscapeGuid.B, LandscapeGuid.C, LandscapeGuid.D);

if (!BoundsArrayPtr) {
auto& BoundsArrayRef = FLandscapeRenderSystem::LandscapeSystemClusterLocalBounds.Emplace(LandscapeGuid, TArray<FBoxSphereBounds>());
BoundsArrayRef.AddZeroed(NumCluster);
Expand Down Expand Up @@ -6654,6 +6657,8 @@ void ULandscapeComponent::GeneratePlatformVertexData(const ITargetPlatform* Targ
BoundsArrayRef[LinearIndex] = CalcBound;
}
}

return;
}
}
//@StarLight code - END LandScapeInstance, Added by yanjianhong
Expand Down
108 changes: 56 additions & 52 deletions Engine/Source/Runtime/Landscape/Private/LandscapeRender.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@ void FLandscapeRenderSystem::RegisterEntity(FLandscapeComponentSceneProxy* Scene
uint32 CurComponentClusterSize = (SceneProxy->ComponentSizeQuads + SceneProxy->NumSubsections) / FLandscapeClusterVertexBuffer::ClusterQuadSize;
check(PerComponentClusterSize == CurComponentClusterSize);

//多线程执行该函数?
InitialClusterBaseAndBound(SceneProxy);
}
//@StarLight code - END LandScapeInstance, Added by yanjianhong
Expand Down Expand Up @@ -872,6 +871,12 @@ void FLandscapeRenderSystem::ResizeAndMoveTo(FIntPoint NewMin, FIntPoint NewSize

void FLandscapeRenderSystem::PrepareView(const FSceneView* View)
{
//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
//#TODO: remove
if (bUseInstanceLandscape)
return;
//@StarLight code - END LandScapeInstance, Added by yanjianhong

const bool bExecuteInParallel = FApp::ShouldUseThreadingForPerformance()
&& GRenderingThread; // Rendering thread is required to safely use rendering resources in parallel.

Expand All @@ -891,40 +896,39 @@ void FLandscapeRenderSystem::BeginRenderView(const FSceneView* View)
{
TRACE_CPUPROFILER_EVENT_SCOPE(FLandscapeRenderSystem::BeginRenderView());

if (FetchHeightmapLODBiasesEventRef.IsValid())
{
FTaskGraphInterface::Get().WaitUntilTaskCompletes(FetchHeightmapLODBiasesEventRef, ENamedThreads::GetRenderThread_Local());
FetchHeightmapLODBiasesEventRef.SafeRelease();
//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
//#TODO: Remove this
if (bUseInstanceLandscape) {
UpdateCluterGPUBuffer();
}
else {
if (FetchHeightmapLODBiasesEventRef.IsValid())
{
FTaskGraphInterface::Get().WaitUntilTaskCompletes(FetchHeightmapLODBiasesEventRef, ENamedThreads::GetRenderThread_Local());
FetchHeightmapLODBiasesEventRef.SafeRelease();
}

if (PerViewParametersTasks.Contains(View))
{
FTaskGraphInterface::Get().WaitUntilTaskCompletes(PerViewParametersTasks[View], ENamedThreads::GetRenderThread_Local());
PerViewParametersTasks.Remove(View);
}
if (PerViewParametersTasks.Contains(View))
{
FTaskGraphInterface::Get().WaitUntilTaskCompletes(PerViewParametersTasks[View], ENamedThreads::GetRenderThread_Local());
PerViewParametersTasks.Remove(View);
}

{
FScopeLock Lock(&CachedValuesCS);
{
FScopeLock Lock(&CachedValuesCS);

SectionLODValues = CachedSectionLODValues[View];
SectionLODValues = CachedSectionLODValues[View];

if (TessellationFalloffSettings.UseTessellationComponentScreenSizeFalloff && NumEntitiesWithTessellation > 0)
{
SectionTessellationFalloffC = CachedSectionTessellationFalloffC[View];
SectionTessellationFalloffK = CachedSectionTessellationFalloffK[View];
if (TessellationFalloffSettings.UseTessellationComponentScreenSizeFalloff && NumEntitiesWithTessellation > 0)
{
SectionTessellationFalloffC = CachedSectionTessellationFalloffC[View];
SectionTessellationFalloffK = CachedSectionTessellationFalloffK[View];
}
}
}

//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
//#TODO: Remove this
if (bUseInstanceLandscape) {
UpdateCluterGPUBuffer();
}
else{
//
check(Min.X == 0 && Min.Y == 0);
RecreateBuffers(View);
}

//@StarLight code - END LandScapeInstance, Added by yanjianhong
}

Expand Down Expand Up @@ -1061,35 +1065,34 @@ void FLandscapeRenderSystem::InitialClusterBaseAndBound(FLandscapeComponentScene

void FLandscapeRenderSystem::CreateAllClusterBuffers(const FGuid& InGuid) {

uint32 NumCluster = ComponentTotalSize.X * ComponentTotalSize.Y * PerComponentClusterSize * PerComponentClusterSize;
uint32 NumComponent = ComponentTotalSize.X * ComponentTotalSize.Y;
uint32 NumCluster = NumComponent * PerComponentClusterSize * PerComponentClusterSize;


const auto& ClusterLocalBounds = FLandscapeRenderSystem::LandscapeSystemClusterLocalBounds.FindChecked(InGuid);

//Copy to new array
ClusterBounds = ClusterLocalBounds;

ClusterBaseData.AddZeroed(NumCluster);
ClusterLodInt.AddZeroed(NumCluster);

check(!ClusterInstanceData_GPU.Buffer.IsValid() && !ClusterInstanceData_GPU.SRV.IsValid());
ClusterInstanceData_GPU.Initialize(sizeof(FClusterInstanceData), NumCluster, PF_R8G8B8A8_UINT, BUF_Dynamic);
ClusterInstanceData_CPU.AddZeroed(NumCluster);

//#TODO: PF_R16F
ClusterLODValues_GPU.Initialize(sizeof(FClusterLodAndLodBiasData), NumCluster, PF_G16R16F, BUF_Dynamic);
ClusterLODValues_CPU.AddZeroed(NumCluster);


ComponentLodInt.AddZeroed(NumComponent);
ComponentLODValues_GPU.Initialize(sizeof(FComponentLodAndLodBiasData), NumComponent, PF_G16R16F, BUF_Dynamic);
ComponentLODValues_CPU.AddZeroed(NumComponent);
}


void FLandscapeRenderSystem::UpdateCluterGPUBuffer() {

SCOPE_CYCLE_COUNTER(STAT_LandscapeClusterUpdateGPUBuffer);
//#TODO: 不需要每次Draw更新, 应该每帧更新一次即可
float* GpuLodData = (float*)RHILockVertexBuffer(ClusterLODValues_GPU.Buffer, 0, ClusterLODValues_GPU.NumBytes, RLM_WriteOnly);
FMemory::Memcpy(GpuLodData, ClusterLODValues_CPU.GetData(), ClusterLODValues_GPU.NumBytes);
RHIUnlockVertexBuffer(ClusterLODValues_GPU.Buffer);
float* GpuLodData = (float*)RHILockVertexBuffer(ComponentLODValues_GPU.Buffer, 0, ComponentLODValues_GPU.NumBytes, RLM_WriteOnly);
FMemory::Memcpy(GpuLodData, ComponentLODValues_CPU.GetData(), ComponentLODValues_GPU.NumBytes);
RHIUnlockVertexBuffer(ComponentLODValues_GPU.Buffer);

void* GpuInstanceData = RHILockVertexBuffer(ClusterInstanceData_GPU.Buffer, 0, ClusterInstanceData_GPU.NumBytes, RLM_WriteOnly);
FMemory::Memcpy(GpuInstanceData, ClusterInstanceData_CPU.GetData(), ClusterInstanceData_GPU.NumBytes);
Expand Down Expand Up @@ -1119,22 +1122,19 @@ void FLandscapeRenderSystem::ComputeClusterPerViewTask(const FVector& ViewOrigin

for (int32 EntityIndex = 0; EntityIndex < SceneProxies.Num(); EntityIndex++){
FLandscapeComponentSceneProxyInstanceMobile* SceneProxy = static_cast<FLandscapeComponentSceneProxyInstanceMobile*>(SceneProxies[EntityIndex]);
check(SceneProxy);
float SectionLODBias = ((FTexture2DResource*)SceneProxy->HeightmapTexture->Resource)->GetCurrentFirstMip();
float ComponentLODBias = ((FTexture2DResource*)SceneProxy->HeightmapTexture->Resource)->GetCurrentFirstMip();

uint32 StartIndex = SceneProxy->ComponenLinearStartIndex;
uint32 EndIndex = SceneProxy->ComponenLinearStartIndex + PerComponentClusterSize * PerComponentClusterSize;
for (uint32 i = StartIndex; i < EndIndex ; ++i) {
float MeshScreenSizeSquared = ComputeBoundsScreenRadiusSquared(ClusterBounds[i].Origin, ClusterBounds[i].SphereRadius, ViewOrigin, ProjMatrix);
float FractionalLOD;
ClusterLodInt[i] = GetClusterLODFromScreenSize(ClusterLODSetting, MeshScreenSizeSquared, LODScale * LODScale, FractionalLOD);
ClusterLODValues_CPU[i].ClusterLod = FractionalLOD;
ClusterLODValues_CPU[i].ClusterLodBias = SectionLODBias;
}
uint32 ComponentLinearIndex = GetComponentLinearIndex(SceneProxy->ComponentBase);

float MeshScreenSizeSquared = ComputeBoundsScreenRadiusSquared(SceneProxy->GetBounds().Origin, SceneProxy->GetBounds().SphereRadius, ViewOrigin, ProjMatrix);
float FractionalLOD;

ComponentLodInt[ComponentLinearIndex] = GetClusterLODFromScreenSize(ClusterLODSetting, MeshScreenSizeSquared, LODScale * LODScale, FractionalLOD);
ComponentLODValues_CPU[ComponentLinearIndex].ComponentLod = FractionalLOD; //要保证最小LOD大于等于TextureStreaming的等级
ComponentLODValues_CPU[ComponentLinearIndex].ComponentLodBias = ComponentLODBias;
}
}


//@StarLight code - END LandScapeInstance, Added by yanjianhong


Expand Down Expand Up @@ -1231,6 +1231,12 @@ void FLandscapeRenderSystem::RecreateBuffers(const FSceneView* InView /* = nullp

void FLandscapeRenderSystem::BeginFrame()
{
//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
//#TODO: remove
if (bUseInstanceLandscape)
return;
//@StarLight code - END LandScapeInstance, Added by yanjianhong

CachedView = nullptr;

CachedSectionLODValues.Empty();
Expand Down Expand Up @@ -1469,13 +1475,11 @@ FLandscapeComponentSceneProxy::FLandscapeComponentSceneProxy(ULandscapeComponent
SetLevelColor(FLinearColor(1.f, 1.f, 1.f));

//@StarLight code - BEGIN LandScapeInstance, Added by yanjianhong
if (FeatureLevel <= ERHIFeatureLevel::ES3_1)
if (FeatureLevel <= ERHIFeatureLevel::ES3_1 && CVarMobileAllowLandScapeInstance.GetValueOnAnyThread() == 0)
{
if (CVarMobileAllowLandScapeInstance.GetValueOnAnyThread() == 0) {
HeightmapTexture = nullptr;
}
HeightmapSubsectionOffsetU = 0;
HeightmapSubsectionOffsetV = 0;
HeightmapTexture = nullptr;
}
else
{
Expand Down
51 changes: 36 additions & 15 deletions Engine/Source/Runtime/Landscape/Private/LandscapeRenderMobile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ class FLandscapeInstanceVertexFactoryVSParameters : public FVertexFactoryShaderP
TexCoordOffsetParameter.Bind(ParameterMap, TEXT("TexCoordOffset"));
InstanceOffset.Bind(ParameterMap, TEXT("InstanceOffset"));
ClusterInstanceDataBuffer.Bind(ParameterMap, TEXT("ClusterInstanceDataBuffer"));
ClusterLodBuffer.Bind(ParameterMap, TEXT("ClusterLodBuffer"));
ComponentLODBuffer.Bind(ParameterMap, TEXT("ComponentLODBuffer"));
}

void GetElementShaderBindings(
Expand Down Expand Up @@ -695,14 +695,14 @@ class FLandscapeInstanceVertexFactoryVSParameters : public FVertexFactoryShaderP
//Update与Bind是分开的,Bind开销是比较小的
ShaderBindings.Add(InstanceOffset, BatchElementParams->InstanceOffsetContainer[static_cast<uint32>(BatchElement.InstancedLODIndex)]);
ShaderBindings.Add(ClusterInstanceDataBuffer, BatchElementParams->ClusterInstanceDataBuffer->SRV);
ShaderBindings.Add(ClusterLodBuffer, BatchElementParams->ClusterLodBuffer->SRV);
ShaderBindings.Add(ComponentLODBuffer, BatchElementParams->ComponentLODBuffer->SRV);
}

protected:
LAYOUT_FIELD(FShaderParameter, TexCoordOffsetParameter);
LAYOUT_FIELD(FShaderParameter, InstanceOffset)
LAYOUT_FIELD(FShaderResourceParameter, ClusterInstanceDataBuffer)
LAYOUT_FIELD(FShaderResourceParameter, ClusterLodBuffer)
LAYOUT_FIELD(FShaderResourceParameter, ComponentLODBuffer)
};

class FLandscapeInstanceVertexFactoryPSParameters : public FVertexFactoryShaderParameters
Expand Down Expand Up @@ -821,16 +821,30 @@ void FLandscapeComponentSceneProxyInstanceMobile::CreateRenderThreadResources()
}


//计算LOD相关参数,不放在构造函数中的原因是LodSetting只会存储一份
//#TODO: Move To new RenderSystem
{
//面积递减系数为ScreenSizeRatioDivider
const auto NumClusterLod = FMath::CeilLogTwo(FLandscapeClusterVertexBuffer::ClusterQuadSize) + 1;

check(HeightmapTexture != nullptr && HeightmapTexture->Resource != nullptr);

uint32 SectionMaxLod = FMath::CeilLogTwo(SubsectionSizeVerts) - 1;

//#TODO: Remove
const uint32 FirstMip = ((FTexture2DResource*)HeightmapTexture->Resource)->GetCurrentFirstMip();
check(SectionMaxLod >= FirstMip);
//// Make sure out LastLOD is > of MinStreamedLOD otherwise we would not be using the right LOD->MIP, the only drawback is a possible minor memory usage for overallocating static mesh element batch
//const int32 MinStreamedLOD = FMath::Min<int32>(FirstMip, SectionMaxLod);

//ClusterMaxLOD <= SectionMaxLod
const uint32 LastClusterLOD = FMath::Min(NumClusterLod - 1, SectionMaxLod);


//处理LOD0,单独参数
float ScreenSizeRatioDivider = FMath::Max(LandscapeComponent->GetLandscapeProxy()->LOD0DistributionSetting, 1.01f);
float CurrentScreenSizeRatio = LandscapeComponent->GetLandscapeProxy()->LOD0ScreenSize;
FLandscapeRenderSystem::FClusterLODSetting& ClusterLodSetting = ClusterRenderSystem->ClusterLODSetting;
ClusterLodSetting.LastLODIndex = NumClusterLod - 1;
ClusterLodSetting.LastLODIndex = static_cast<int8>(LastClusterLOD);
ClusterLodSetting.LOD0ScreenSizeSquared = FMath::Square(CurrentScreenSizeRatio);

//LOD1
Expand Down Expand Up @@ -873,7 +887,7 @@ void FLandscapeComponentSceneProxyInstanceMobile::CreateRenderThreadResources()

ComponentBatchUserData.LandscapeComponentClusterUniformBuffer = &ComponentClusterUniformBuffer;
ComponentBatchUserData.ClusterInstanceDataBuffer = &ClusterRenderSystem->ClusterInstanceData_GPU;
ComponentBatchUserData.ClusterLodBuffer = &ClusterRenderSystem->ClusterLODValues_GPU;
ComponentBatchUserData.ComponentLODBuffer = &ClusterRenderSystem->ComponentLODValues_GPU;
ComponentBatchUserData.InstanceOffsetContainer.AddZeroed(SharedBuffers->NumClusterLOD);

LodInstanceDataSparseArray.AddZeroed(SharedBuffers->NumClusterLOD);
Expand Down Expand Up @@ -913,6 +927,8 @@ void FLandscapeComponentSceneProxyInstanceMobile::GetDynamicMeshElements(const T
{
SCOPE_CYCLE_COUNTER(STAT_LandscapeClusterFrustumCull);
uint32 ComponentClusterSize = ClusterRenderSystem->PerComponentClusterSize;
uint32 ComponentLinearIndex = ClusterRenderSystem->GetComponentLinearIndex(ComponentBase);
uint32 ClusterLod = ClusterRenderSystem->ComponentLodInt[ComponentLinearIndex];
//uint32 StartComponentLinearIndex = ClusterRenderSystem->GetClusterLinearIndex(ComponentBase, FIntPoint(0, 0));

for (uint32 ComponentClusterIndex = 0; ComponentClusterIndex < ComponentClusterSize * ComponentClusterSize; ++ComponentClusterIndex) {
Expand All @@ -923,13 +939,16 @@ void FLandscapeComponentSceneProxyInstanceMobile::GetDynamicMeshElements(const T
continue;
}

//
//#TODO: Debug Only
if (ViewFamily.EngineShowFlags.Bounds) {

//float TestA = ClusterRenderSystem->ClusterLODValues_CPU[ClusterLinearIndex].ClusterLod.GetFloat();
//float TestB = ClusterRenderSystem->ClusterLODValues_CPU[ClusterLinearIndex].ClusterLodBias.GetFloat();
//check(TestA >= TestB);
RenderOnlyBox(Collector.GetPDI(0), ClusterBound);
}

//#TODO: LOD容器
uint32 ClusterLod = ClusterRenderSystem->ClusterLodInt[ClusterLinearIndex];

//按照顺序将数据收集,同级LOD数据打包到一起
NonConstLodInstanceDataSparseArray[ClusterLod].Emplace(ClusterRenderSystem->ClusterBaseData[ClusterLinearIndex]);
Expand Down Expand Up @@ -1069,10 +1088,12 @@ void FLandscapeComponentSceneProxyInstanceMobile::OnTransformChanged() {
// Set FLandscapeUniformVSParameters for this Component
FLandscapeComponentClusterUniformBuffer LandscapeClusterParams;

check(FMath::IsPowerOfTwo(SubsectionSizeVerts));

LandscapeClusterParams.ClusterParameter = FVector4(
PerComponentClusterSize,
1.f / (float)SubsectionSizeQuads,
FLandscapeClusterVertexBuffer::ClusterQuadSize,
NumSubsections,
0
);

Expand All @@ -1090,12 +1111,12 @@ void FLandscapeComponentSceneProxyInstanceMobile::OnTransformChanged() {
LightmapBiasY,
LightmapBiasX);

//LandscapeClusterParams.SubsectionSizeVertsLayerUVPan = FVector4(
// SubsectionSizeVerts,
// 1.f / (float)SubsectionSizeQuads,
// SectionBase.X,
// SectionBase.Y
//);
LandscapeClusterParams.SubsectionSizeVertsLayerUVPan = FVector4(
SubsectionSizeVerts,
1.f / (float)SubsectionSizeQuads,
SectionBase.X,
SectionBase.Y
);

LandscapeClusterParams.SubsectionOffsetParams = FVector4(
HeightmapSubsectionOffsetU,
Expand Down
Loading

0 comments on commit 28fe0d2

Please sign in to comment.