From b3d18f3b0e4722f1deb894bf67191d439fa32d4e Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 21 Apr 2022 12:39:27 +0200 Subject: [PATCH] Improve `StaticModel` to register for Scene Rendering once the model has any LOD streamed-in --- Source/Engine/Level/Actors/StaticModel.cpp | 59 ++++++++++++++++++-- Source/Engine/Level/Actors/StaticModel.h | 4 ++ Source/Engine/Level/Scene/SceneRendering.cpp | 6 ++ Source/Engine/Level/Scene/SceneRendering.h | 2 + 4 files changed, 67 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index a32512b1b..41cb38515 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -163,20 +163,46 @@ void StaticModel::RemoveVertexColors() void StaticModel::OnModelChanged() { + if (_residencyChangedModel) + { + _residencyChangedModel = nullptr; + Model->ResidencyChanged.Unbind(this); + } RemoveVertexColors(); Entries.Release(); - if (Model && !Model->IsLoaded()) - { UpdateBounds(); - } + else if (!Model && _sceneRenderingKey != -1) + GetSceneRendering()->RemoveActor(this, _sceneRenderingKey); } void StaticModel::OnModelLoaded() { Entries.SetupIfInvalid(Model); - UpdateBounds(); + if (_sceneRenderingKey == -1 && _scene) + { + // Register for rendering but once the model has any LOD loaded + if (Model->GetLoadedLODs() == 0) + { + _residencyChangedModel = Model; + Model->ResidencyChanged.Bind(this); + } + else + { + _sceneRenderingKey = GetSceneRendering()->AddActor(this); + } + } +} + +void StaticModel::OnModelResidencyChanged() +{ + if (_sceneRenderingKey == -1 && _scene && Model && Model->GetLoadedLODs() > 0) + { + _sceneRenderingKey = GetSceneRendering()->AddActor(this); + _residencyChangedModel = nullptr; + Model->ResidencyChanged.Unbind(this); + } } void StaticModel::UpdateBounds() @@ -488,3 +514,28 @@ void StaticModel::OnTransformChanged() _transform.GetWorld(_world); UpdateBounds(); } + +void StaticModel::OnEnable() +{ + if (_scene && Model && Model->IsLoaded() && Model->GetLoadedLODs() > 0 && _sceneRenderingKey == -1) + _sceneRenderingKey = GetSceneRendering()->AddActor(this); + + // Skip ModelInstanceActor (add to SceneRendering manually) + Actor::OnEnable(); +} + +void StaticModel::OnDisable() +{ + // Skip ModelInstanceActor (add to SceneRendering manually) + Actor::OnDisable(); + + if (_sceneRenderingKey != -1) + { + GetSceneRendering()->RemoveActor(this, _sceneRenderingKey); + } + else if (_residencyChangedModel) + { + _residencyChangedModel = nullptr; + Model->ResidencyChanged.Unbind(this); + } +} diff --git a/Source/Engine/Level/Actors/StaticModel.h b/Source/Engine/Level/Actors/StaticModel.h index 60f0355bf..db0ece1a6 100644 --- a/Source/Engine/Level/Actors/StaticModel.h +++ b/Source/Engine/Level/Actors/StaticModel.h @@ -25,6 +25,7 @@ private: byte _vertexColorsCount; Array _vertexColorsData[MODEL_MAX_LODS]; GPUBuffer* _vertexColorsBuffer[MODEL_MAX_LODS]; + Model* _residencyChangedModel = nullptr; public: @@ -182,6 +183,7 @@ private: void OnModelChanged(); void OnModelLoaded(); + void OnModelResidencyChanged(); void UpdateBounds(); public: @@ -199,4 +201,6 @@ protected: // [ModelInstanceActor] void OnTransformChanged() override; + void OnEnable() override; + void OnDisable() override; }; diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp index c29db6bee..3090fd798 100644 --- a/Source/Engine/Level/Scene/SceneRendering.cpp +++ b/Source/Engine/Level/Scene/SceneRendering.cpp @@ -6,6 +6,7 @@ #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderView.h" #include "Engine/Renderer/RenderList.h" +#include "Engine/Threading/Threading.h" #if SCENE_RENDERING_USE_PROFILER #include "Engine/Profiler/ProfilerCPU.h" #endif @@ -29,6 +30,7 @@ void ISceneRenderingListener::ListenSceneRendering(SceneRendering* scene) void SceneRendering::Draw(RenderContext& renderContext) { + ScopeLock lock(Locker); auto& view = renderContext.View; const BoundingFrustum frustum = view.CullingFrustum; renderContext.List->Scenes.Add(this); @@ -90,6 +92,7 @@ void SceneRendering::CollectPostFxVolumes(RenderContext& renderContext) void SceneRendering::Clear() { + ScopeLock lock(Locker); for (auto* listener : _listeners) { listener->OnSceneRenderingClear(this); @@ -104,6 +107,7 @@ void SceneRendering::Clear() int32 SceneRendering::AddActor(Actor* a) { + ScopeLock lock(Locker); int32 key = 0; // TODO: track removedCount and skip searching for free entry if there is none for (; key < Actors.Count(); key++) @@ -125,6 +129,7 @@ int32 SceneRendering::AddActor(Actor* a) void SceneRendering::UpdateActor(Actor* a, int32 key) { + ScopeLock lock(Locker); if (Actors.IsEmpty()) return; auto& e = Actors[key]; @@ -137,6 +142,7 @@ void SceneRendering::UpdateActor(Actor* a, int32 key) void SceneRendering::RemoveActor(Actor* a, int32& key) { + ScopeLock lock(Locker); if (Actors.HasItems()) { auto& e = Actors[key]; diff --git a/Source/Engine/Level/Scene/SceneRendering.h b/Source/Engine/Level/Scene/SceneRendering.h index 160a89510..9aed3e3b7 100644 --- a/Source/Engine/Level/Scene/SceneRendering.h +++ b/Source/Engine/Level/Scene/SceneRendering.h @@ -6,6 +6,7 @@ #include "Engine/Core/Collections/Array.h" #include "Engine/Core/Math/BoundingSphere.h" #include "Engine/Level/Actor.h" +#include "Engine/Platform/CriticalSection.h" class SceneRenderTask; class SceneRendering; @@ -75,6 +76,7 @@ public: Array Actors; Array PostFxProviders; + CriticalSection Locker; private: #if USE_EDITOR