!B (Sandbox) (CE-21795) Importing models with multisubmaterials via fbx switches...
[CRYENGINE.git] / Code / CryEngine / CrySchematyc2 / Services / UpdateScheduler.h
blobdfbbca888eb9a144e3c7f07497b184b6f5654227
1 // Copyright 2001-2019 Crytek GmbH / Crytek Group. All rights reserved.
3 // #SchematycTODO : Inline helper structs and move to .cpp?
4 // #SchematycTODO : Sort slots by scope address?
6 #pragma once
8 #include <CrySchematyc2/Services/IUpdateScheduler.h>
9 #include <ILevelSystem.h>
11 #ifndef _RELEASE
12 #define DEBUG_RELEVANCE_GRID (1)
13 #define DEBUG_BUCKETS_NAMES (1)
14 #endif
16 namespace Schematyc2
18 class CUpdateScheduler;
20 // A simple grid implementation, which is connecting/disconnecting schematyc component updates based on relevant entities (players)
21 class CRelevanceGrid
22 : public ISystemEventListener
23 , public ILevelSystemListener
25 public:
26 enum ECellChangedResult
28 eCellChangedResult_Same,
29 eCellChangedResult_Changed,
30 eCellChangedResult_NotFound,
31 eCellChangedResult_Count
34 // Stores all the info needed to hook a update callback from schematyc components
35 struct SUpdateCallback
37 SUpdateCallback(CUpdateScope* pScope, const UpdateCallback& callback, UpdateFrequency frequency, UpdatePriority priority, const UpdateFilter& filter);
39 CUpdateScope* pScope;
40 UpdateCallback callback;
41 UpdateFrequency frequency;
42 UpdatePriority priority;
43 UpdateFilter filter;
46 typedef std::vector<SUpdateCallback> TUpdateCallbacks;
48 // Add more information here in case we need better filtering for dynamic objects
49 struct SDynamicObject
51 SDynamicObject(CUpdateScope* pScope, const UpdateCallback& callback, UpdateFrequency frequency, UpdatePriority priority, const UpdateFilter& filter);
53 SUpdateCallback updateCallback;
56 typedef std::vector<SDynamicObject> TDynamicObjects;
58 struct SGridCell
60 SGridCell()
61 : relevanceCounter(0)
64 TUpdateCallbacks globalUpdateCallbacks;
65 TUpdateCallbacks localGridUpdateCallbacks;
66 short relevanceCounter;
69 typedef std::vector<SGridCell> TGridCells;
71 struct SRelevantCell
73 SRelevantCell()
74 : x(0)
75 , y(0)
76 , cellIdx(0)
77 , id(INVALID_ENTITYID)
78 , bIsLocal(false)
81 SRelevantCell(ushort x, ushort y, ushort cellIdx, EntityId id, bool bIsLocal)
82 : x(x)
83 , y(y)
84 , cellIdx(cellIdx)
85 , id(id)
86 , bIsLocal(bIsLocal)
89 ushort x;
90 ushort y;
91 ushort cellIdx;
92 bool bIsLocal;
93 EntityId id;
96 typedef std::vector<SRelevantCell> TRelevantCells;
98 public:
99 CRelevanceGrid();
100 virtual ~CRelevanceGrid();
102 // ISystemEventListener
103 virtual void OnSystemEvent(ESystemEvent event, UINT_PTR wparam, UINT_PTR lparam) override;
104 // ~ISystemEventListener
106 // ILevelSystemListener
107 virtual void OnLoadingLevelEntitiesStart(ILevelInfo* pLevel) override;
108 // ~ILevelSystemListener
110 bool Register(CUpdateScope* pScope, const UpdateCallback& callback, UpdateFrequency frequency, UpdatePriority priority, const UpdateFilter& filter);
111 void Unregister(CUpdateScope* pScope);
112 bool RegisterDynamicObject(CUpdateScope* pScope, const UpdateCallback& callback, UpdateFrequency frequency, UpdatePriority priority, const UpdateFilter& filter);
113 void UnregisterDynamicObject(CUpdateScope* pScope);
114 void Update(CUpdateRelevanceContext* pRelevanceContext = nullptr);
115 void SetUpdateScheduler(CUpdateScheduler* pScheduler);
117 private:
118 void Construct();
119 void SetupUpdateCallbacksAroundCell(ushort cellX, ushort cellY, bool bIsLocal, bool bConnect);
120 void ConnectCell(ushort idx, bool bIsLocal);
121 void DisconnectCell(ushort idx, bool bIsLocal);
122 ECellChangedResult DidRelevantCellIndexChange(const SRelevantCell& cellToFind, SRelevantCell*& pCellInfo);
123 void GetCellCoordinates(const Vec3 worldPos, ushort &x, ushort& y, ushort& cellIdx) const;
124 ushort GetCellIndex(ushort x, ushort y) const;
126 #if DEBUG_RELEVANCE_GRID
127 void DebugDrawStatic(CUpdateRelevanceContext* pRelevanceContext);
128 void DebugLogStaticMemoryStats();
129 #endif
131 private:
132 TGridCells m_grid;
133 TDynamicObjects m_dynamicObjects;
134 TRelevantCells m_relevantCells;
135 CUpdateScheduler* m_pUpdateScheduler;
136 std::vector<Vec3> m_relevantEntitiesWorldPos;
137 int m_gridSize; // The grid size. Its a square so m_gridSize x m_gridSize
138 int m_gridSizeMinusOne; // Cached constantly needed value
139 int m_updateHalfDistance; // The update distance around the relevant cells in cells (e.g. 1, 2... cells)
141 #if DEBUG_RELEVANCE_GRID
142 int m_debugUpdateFrame;
143 #endif
146 class CUpdateScheduler : public IUpdateScheduler
148 friend class CRelevanceGrid;
150 public:
152 CUpdateScheduler();
154 ~CUpdateScheduler();
156 // IUpdateScheduler
157 virtual bool Connect(CUpdateScope& scope, const UpdateCallback& callback, UpdateFrequency frequency = EUpdateFrequency::EveryFrame, UpdatePriority priority = EUpdatePriority::Default, const UpdateFilter& filter = UpdateFilter()) override;
158 virtual void Disconnect(CUpdateScope& scope) override;
159 virtual bool InFrame() const override;
160 virtual bool BeginFrame(float frameTime) override;
161 virtual bool Update(UpdatePriority beginPriority = EUpdateStage::PrePhysics | EUpdateDistribution::Earliest, UpdatePriority endPriority = EUpdateStage::Post | EUpdateDistribution::End, CUpdateRelevanceContext* pRelevanceContext = nullptr) override;
162 virtual bool EndFrame() override;
163 virtual void VerifyCleanup() override;
164 virtual void Reset() override;
165 virtual const UpdateSchedulerStats::IFrameUpdateStats* GetFrameUpdateStats() const override;
166 virtual void SetShouldUseRelevanceGridCallback(UseRelevanceGridPredicate directConnect) override;
167 virtual void SetIsDynamicObjectCallback(IsDynamicObjectPredicate isDynamicObject) override;
168 virtual void SetDebugPriorityNames(const DebugPriorityNameArray& debugNames) override;
169 // ~IUpdateScheduler
171 private:
173 bool ConnectInternal(CUpdateScope& scope, const UpdateCallback& callback, UpdateFrequency frequency = EUpdateFrequency::EveryFrame, UpdatePriority priority = EUpdatePriority::Default, const UpdateFilter& filter = UpdateFilter());
174 void DisconnectInternal(CUpdateScope &scope);
175 void UnregisterFromRelevanceGrid(CUpdateScope& scope);
177 struct SUpdateSlot
179 SUpdateSlot();
180 SUpdateSlot(const UpdatePriority priority, const UpdateFrequency frequency);
182 UpdatePriority priority;
183 UpdateFrequency bucketIndex;
185 inline bool operator <(const SUpdateSlot& rhs) const
187 return priority > rhs.priority;
191 typedef std::vector<SUpdateSlot> TUpdateSlots;
193 struct SObserver
195 SObserver();
196 SObserver(CUpdateScope& scope, const UpdateCallback& callback, const UpdateFilter& filter, UpdateFrequency frequency, UpdateFrequency stride);
198 CUpdateScope* pScope;
199 UpdateCallback callback;
200 UpdateFilter filter;
201 UpdateFrequency frequency : 8;
202 UpdateFrequency stride : 8;
204 static_assert(sizeof(UpdateFrequency) == 2, "UpdateFrequency expected to be 16 bit");
207 typedef std::vector<SObserver> TObserverVector;
209 struct SPendingObserver : public SObserver
211 SPendingObserver();
212 SPendingObserver(CUpdateScope& scope, const UpdateCallback& callback, const UpdateFilter& filter, UpdateFrequency frequency, UpdateFrequency stride, UpdatePriority priority);
214 UpdatePriority priority;
217 struct SFrameUpdateStats : public UpdateSchedulerStats::IFrameUpdateStats
219 enum { k_maxStagesCount = 8 };
220 enum { k_maxBucketsCount = EUpdateFrequency::Count };
222 SFrameUpdateStats();
224 void Add(const UpdateSchedulerStats::SUpdateStageStats& stats);
225 void AddConnected(int64 timeTicks);
226 void AddDisconnected(int64 timeTicks);
227 void Reset();
229 virtual const UpdateSchedulerStats::SUpdateStageStats* GetStageStats(size_t& outCount) const override;
230 virtual const UpdateSchedulerStats::SUpdateBucketStats* GetBucketStats(size_t& outCount) const override;
231 virtual const UpdateSchedulerStats::SChangeStats* GetChangeStats() const override { return &changeStats; }
233 UpdateSchedulerStats::SUpdateStageStats stagesStats[k_maxStagesCount];
234 size_t stagesCount;
235 UpdateSchedulerStats::SUpdateBucketStats bucketStats[k_maxBucketsCount];
236 UpdateSchedulerStats::SChangeStats changeStats;
239 typedef std::vector<size_t> TDirtyIndicesVector;
241 struct SObserverGroup
243 SObserverGroup();
245 TObserverVector observers;
246 TDirtyIndicesVector dirtyIndices;
249 typedef VectorMap<UpdatePriority, SObserverGroup> TObserverMap;
250 typedef std::vector<SPendingObserver> TPendingObservers;
251 typedef std::vector<UpdatePriority> TPendingPriorities;
252 typedef VectorMap<UpdatePriority, const char*> TPriorityDebugNameMap;
254 class CBucket
256 public:
257 struct SUpdateStats;
259 CBucket();
261 void Connect(CUpdateScope& scope, const UpdateCallback& callback, UpdateFrequency frequency, UpdatePriority priority, const UpdateFilter& filter);
262 void Disconnect(CUpdateScope& scope, UpdatePriority priority);
263 void BeginUpdate(TPendingPriorities& pendingPriorities);
264 template <bool UseStride>
265 void Update(const SUpdateContext context, UpdatePriority priority, uint32 frameId, UpdateSchedulerStats::SUpdateBucketStats& outUpdateStats, const TPriorityDebugNameMap& debugNames);
266 void Reset();
267 void CleanUp();
268 void SetFrequency(UpdateFrequency frequency);
270 private:
271 UpdateFrequency SelectNewStride() const;
272 void AddObserver(TObserverVector& observers, CUpdateScope& scope, const UpdateCallback& callback, const UpdateFilter& filter);
273 void DeleteDirtyObservers();
274 void AddPendingObservers(TPendingPriorities& pendingPriorities);
275 const char* GetDebugName(UpdatePriority priority, const TPriorityDebugNameMap& debugNames);
277 private:
279 TObserverMap m_observers;
280 TPendingObservers m_pendingNewPriorityObservers;
281 size_t m_totalObserverCount;
282 size_t m_totalDirtyCount;
283 std::vector<size_t> m_frameStrideBuckets;
284 UpdateFrequency m_frequency;
287 static const size_t s_maxFrameStride = 1 << (EUpdateFrequency::Count - 1);
290 CBucket m_buckets[EUpdateFrequency::Count];
291 TUpdateSlots m_updateOrder;
292 size_t m_updatePosition;
293 float m_frameTimes[s_maxFrameStride];
294 uint32 m_frameIdx;
295 bool m_bInFrame;
297 TPriorityDebugNameMap m_debugNameMap;
298 SFrameUpdateStats m_stats;
299 TPendingPriorities m_pendingPriorities;
300 // Relevance grid related members
301 CRelevanceGrid m_relevanceGrid;
302 IUpdateScheduler::UseRelevanceGridPredicate m_useRelevanceGrid;
303 IUpdateScheduler::IsDynamicObjectPredicate m_isDynamicObject;