gwnavruntime/visualdebug/visualdebugserver.h Source File

visualdebugserver.h
Go to the documentation of this file.
1 /*
2 * Copyright 2016 Autodesk, Inc. All rights reserved.
3 * Use of this software is subject to the terms of the Autodesk license agreement and any attachments or Appendices thereto provided at the time of installation or download,
4 * or which otherwise accompanies this software in either electronic or hard copy form, or which is signed by you and accepted by Autodesk.
5 */
6 
7 
8 #pragma once
9 
21 
22 
23 namespace Kaim
24 {
25 
26 class FileOpenerBase;
27 class File;
28 
29 class ServerStatusChangedCallback;
30 class MessageBlob;
31 class MessageAggregatedBlob;
32 class MessageBlobHandler;
33 class BlobFieldsStore;
34 
35 class Profiler;
36 class FloatStat;
37 class IQuery;
38 
39 class Vec3f;
40 
41 class VisualDebugAttributesManager;
42 
47 {
48  KY_DEFINE_NEW_DELETE_OPERATORS(MemStat_WorldFwk)
49 public:
50  static KyUInt32 DefaultServerPort() { return 4888; }
51  static KyUInt32 DefaultBroadcastPort() { return 4887; }
52 
53 public:
55  enum Mode {
58  };
59 
61  enum WaitOnStart {
64  };
65 
70  };
71 
73  enum RunMode {
76  };
77 
78 public:
81  , m_serverPort(0)
82  , m_broadcastPort(0)
83  , m_waitOnStart(DoNotWaitOnStart)
85  , m_localFileName(nullptr)
86  , m_localFileOpener(nullptr)
92  {}
93 
104  void UseNavigationLab(KyUInt32 serverPort = DefaultServerPort(), KyUInt32 broadcastPort = DefaultBroadcastPort(), MessageReceiverRegistry* navigationLabCommandHandlers = nullptr)
105  {
107  m_navigationLabCommandHandlers = navigationLabCommandHandlers;
108  m_serverPort = serverPort;
109  m_broadcastPort = broadcastPort;
110  m_localFileName = nullptr;
111  m_localFileOpener = nullptr;
112  }
113 
114  void UseLocalFile(const char* localFileName, FileOpenerBase* localFileOpener = nullptr)
115  {
118  m_serverPort = 0;
119  m_localFileName = localFileName;
120  m_localFileOpener = localFileOpener;
121  }
122 
123  void SetLocalFileSizeLimit(KyInt32 localFileMegaBytesLimit) { m_localFileMegaBytesLimit = localFileMegaBytesLimit; }
124 
125  void SetWaitOnStart(WaitOnStart waitOnStart) { m_waitOnStart = waitOnStart; }
126 
128  void SetMemoryConsumption(KyUInt32 expectedKiloBytesPerFrame, KyUInt32 maximumMegaBytesToUse)
129  {
130  m_expectedKiloBytesPerFrame = expectedKiloBytesPerFrame;
131  m_maximumMegaBytes = maximumMegaBytesToUse;
132  }
133 
134  void SetDisconnectionMode(DisconnectionMode disconnectionMode) { m_disconnectionMode = disconnectionMode; }
135 
136  void SetRunMode(RunMode runMode) { m_runMode = runMode; }
137 
138  void SetServerName(const char* serverName) { m_serverName = String(serverName); }
139 
140 public: // internal
143 
144  // ------------- Relevant attributes if #m_mode = Mode_UseNavigationLab. -----------
145 
148 
151 
152  WaitOnStart m_waitOnStart;
153 
157  MessageReceiverRegistry* m_navigationLabCommandHandlers;
158 
159  // ------------- Relevant attributes if #m_mode = Mode_UseLocalFile. -----------
160 
162  const char* m_localFileName;
163 
166 
169 
170  // ------------- Memory allocations of messages -----------
171 
176 
177  // ------------- Various attributes -----------
178 
181 
184 
186  String m_serverName;
187 };
188 
189 }
190 
191 // Define KY_DISABLE_VISUALDEBUGSERVER to disable VisualDebugServer
192 // In that case, it will be replaced by fully inlined classe, DisabledVisualDebugServer,
193 // thanks to the define at the end of this file.
194 // If VisualDebugServer is modified, please apply the changes into disabledvisualdebugserver.inl as well.
195 #if defined(KY_CONFIG_RELEASE) || !defined(KY_ENABLE_SOCKETS)
196 # define KY_DISABLE_VISUALDEBUGSERVER
197 #endif
198 
199 #ifndef KY_DISABLE_VISUALDEBUGSERVER
200 
206 
207 
208 namespace Kaim
209 {
210 
218 class VisualDebugServer
219 {
220  KY_DEFINE_NEW_DELETE_OPERATORS(MemStat_VisualDebug)
221 
222 public:
223  // --------------- Server Status ----------------
224 
228  void NewFrame(KyUInt32 gameFrameIndex = KyUInt32MAXVAL);
229 
231  bool IsStarted() const { return m_isStarted; }
232 
234  bool IsReadyToSend() { return m_isReadyToSend && IsConnectionEstablished(); }
235 
236  // ------------------ Send Statistics ------------------
238 
239  void SendStats(const char* statName, const KyFloat32 value, const KyFloat32 average, const KyFloat32 max, const KyFloat32 min, const char* groupName);
240  void SendStats(const FloatStat& timeStat, const char* groupName);
241  void SendStats(const char* statName, const FloatStat& timeStat, const char* groupName);
242 
243  // ------------------ Send Single Value ------------------
245 
246  void SendUInt32(const char* statName, const KyUInt32 value, const char* groupName);
247  void SendInt32(const char* statName, const KyInt32 value, const char* groupName);
248  void SendFloat32(const char* statName, const KyFloat32 value, const char* groupName);
249  void SendString(const char* statName, const char* value, const char* groupName);
250 
251  // --------------- Send Game-Specific info ---------------
252 
253  void SendGameCamera(const Vec3f& cameraPos, const Vec3f& cameraLookAtPos, const Vec3f& cameraUp, KyFloat32 fovInDegrees);
254  void SendGameCameraAttitude(const Vec3f& cameraPos, const Vec3f& cameraRight, const Vec3f& cameraUp, const Vec3f& cameraFront, KyFloat32 fovInDegrees);
255 
256  // --------------- Advanced usage : Handling Received Blob Messages ----------------
257 
258  void PauseMessageProcessing() { m_messageProcessingIsPaused = true; }
259  void ResumeMessageProcessing() { m_messageProcessingIsPaused = false; }
260 
261 private:
262  KyResult OpenNavigationLabConnection();
263  KyResult OpenFileConnection();
264 
265  KyResult AggregateMessage(Ptr<BaseBlobHandler> handlerPtr);
266  KyResult CreateAggregateMessage(KyUInt32 deepBlobSize);
267  KyResult SendAggregateMessage();
268 
269  KyResult SetupMessageRegistry(MessageReceiverRegistry* receiverRegistry, VisualDebugUnknownBlobTypeHandling unknownBlobTypeHandling = VisualDebugUnknownBlobTypeHandling::Log);
270  KyResult OpenConnection(SocketDispatchMode mode, KyUInt32 port, KyUInt32 broadcastPort, bool initSocketConnection);
271 
272  void AddToStats(KyUInt32 blobtypeId, KyUInt32 deepBlobSize);
273  void ClearStatistics();
274  void SendInternalStatistics();
275 
276  void SendStatGroups();
277  VisualDebugStatGroup* GetStatGroup(const char* groupName);
278  VisualDebugStatGroup* GetOrCreateStatGroup(const char* groupName);
279 
280  void ClearSession(); // clear stats, message, timer, gameFrameIndex
281  void OnDisconnection(); // called in VisualDebugServer's operatingThread to clear the session if OnDisconnectionUnsafeCallback() was called from the socketThread
282  void MakeReadyToSend(); // set m_isConnected to true and apply what has to be done in VisualDebugServer's operatingThread on connection
283 
284  KyResult OnConnectionUnsafeCallback(); // called from the socketThread when connection is established
285  KyResult OnDisconnectionUnsafeCallback(); // called from the socketThread when disconnected
286 
287  void UpdateThreadMgr(bool& out_needToWait);
288 
289  // Checks if there is enough memory before creating a new message
290  void CheckMemory();
291 
292  void InitAttributesManager();
293  void CreateProfilingAttributes();
294  void CreateAdvancedProfilingAttributes();
295  void UpdateProfilingAttributes();
296  void UpdateAdvancedProfilingAttributes();
297 
298  // Used internally. true for NavigationLab, false for LocalFile.
299  void EnableSynchronization(bool enabled) { m_synchronizationEnabled = enabled; }
300 
301  // \return true if synchronization is done
302  bool Synchronize();
303 
304 public: // internal
305 
306  // --------------- For internal use only ----------------
309 
310  VisualDebugServer();
311  ~VisualDebugServer();
312 
313  KyResult Start(const VisualDebugServerConfig& config);
314  KyResult ReStart() { return Start(m_config); }
315  void Stop();
316 
319  static KyUInt32 GetInfiniteWaitDelay() { return KY_WAIT_INFINITE; }
320 
322  bool WaitWhileEstablishingConnection(KyUInt32 maxDelayMilliseconds);
323 
325  void Flush();
326 
331  void SetSimulationTime(KyFloat32 simulationTimeInSeconds) { m_simulationTimeInSeconds = simulationTimeInSeconds; }
332 
335  template <class T>
336  KyResult Send(BaseBlobBuilder<T>& blobBuilder)
337  {
338  const KyUInt32 blobType = T::GetBlobTypeId();
339  Ptr<BaseBlobHandler> blobHandler = m_handlerRegistry.Get(blobType);
340  if (blobHandler == nullptr)
341  {
342  blobHandler = *KY_NEW BlobHandler<T>;
343  m_handlerRegistry.SetVal(blobType, blobHandler);
344  }
345 
346  blobBuilder.Build((BlobHandler<T>&)*blobHandler);
347  return this->AggregateMessage(blobHandler);
348  }
349 
354  KyResult Send(BaseBlobHandler& blobHandler);
355 
356  // Send a IQuery if the inheriting query supports it
357  // _NOTE_: Currently, only used in order to send back the result of a query requested by the NavigationLab.
358  KyResult Send(IQuery* query);
359 
360  // SendLog
361  KyResult SendLog(Kaim::LogMessageId messageId, const char* message);
362 
364  KyResult HandleAllReceivedMessages();
365 
367  KyResult HandleNextReceivedMessage();
368 
370  Ptr<Net::AMP::Message> GetNextReceivedMessage();
371 
373  KyResult HandleMessage(Ptr<Net::AMP::Message> msg);
374 
376  void SetAdvancedInternalStatistics(bool enable) { m_enableAdvancedInternalStatistics = enable; }
377 
379  void SetThreadId(ThreadId threadId) { m_operatingThreadId = threadId; }
380 
382  ThreadId GetThreadId() const { return m_operatingThreadId; }
383 
385  bool CanSafelyOperate() const { return (m_operatingThreadId == GetCurrentThreadId()); }
386 
389  bool IsConnectionEstablished() const;
390 
392  bool IsSynchronizing() { return (m_isReadyToSend == false && IsConnectionEstablished() == true); }
393 
394  // Wait until all messages are sent (or if connection is lost or ended client-side).
395  void WaitForEmptiedSendQueue();
396 
397  // Called when the EndOfSynchronizationBlob Message is received from the NavigationLab
398  void EndOfSynchronizationMessageReceived() { m_endOfSynchronizationMessageReceived = true; }
399 
400  Net::AMP::ThreadMgr* GetThreadMgr() { return m_socketThreadMgr.GetPtr(); }
401  const Net::AMP::ThreadMgr* GetThreadMgr() const { return m_socketThreadMgr.GetPtr(); }
402 
404  MemoryHeap* GetHeap() { return Memory::GetHeapByAddress(m_socketThreadMgr.GetPtr()); }
405 
406  // return a pointer because it allows DisabledVisualDebugServer::GetConfig() to return nullptr
407  const VisualDebugServerConfig* GetConfig() const { return &m_config; }
408 
409  UserBlobRegistry<IDisplayListBuilder>* GetDisplayListBuilderRegistry() { return m_displayListBuilderRegistry; }
410 
411 public: // Deprecated
413  KY_DEPRECATED(bool IsConnected()) { return IsReadyToSend(); }
414 
415 private:
416  // Config
417  VisualDebugServerConfig m_config; // The config passed to Start()
418  KyUInt32 m_defaultGameFrameIndex; // The current frame index
419  KyFloat32 m_simulationTimeInSeconds;
420  Profiler* m_gameFrameTimeProfiler;
421  bool m_synchronizationEnabled;
422 
423  // Status
424  bool m_isStarted; // Set to true between calls to Start and Stop
425  bool m_isConnectionEstablished;
426  bool m_endOfSynchronizationMessageReceived; // Set to true when EndOfSynchronization is received y the client, not though m_isConnected is not yet set to true, NewFrame needs to be called.
427  bool m_isReadyToSend;
428  bool m_wasDisconnected; // Used to cancel previous m_aggregatedBlobMsg
429  ThreadId m_operatingThreadId; // ThreadId of the thread that Send functions and Update are supposed to be called from
430 
431  // Socket/Thread management
432  Ptr<Net::AMP::ThreadMgr> m_socketThreadMgr;
433  Ptr<Net::AMP::DiscardMessageHandler> m_msgDiscarder; // used to discard messages we are not interested in
434  Ptr<MessageBlobHandler> m_msgBlobHandler; // used to handle received MessageBlob
435  SocketDispatcherFactory* m_socketFactory; // in charge of creating the socket depending on VisualDebugServerConfig::Mode
436  Ptr<File> m_file; // used when mode is Mode_UseLocalFile
437 
438  friend class ServerStatusChangedCallback;
439  Ptr<ServerStatusChangedCallback> m_statusCallback; // Callback for connection status change
440  Event m_connectedEvent;
441 
442  // Message construction
443  typedef UserPtrBlobRegistry<BaseBlobHandler> BlobHandlerRegistry;
444  BlobHandlerRegistry m_handlerRegistry;
445  MessageAggregatedBlob* m_aggregatedBlobMsg;
446 
447  // Message reception
448  List<Net::AMP::Message> m_msgList;
449  Kaim::UInt32 m_msgListSize;
450 
451  // Stats
452  KyUInt32 m_messagesNotSentOnWait;
453  KyUInt32 m_memoryLimitReached; // Records if the memory limit was reached during this frame
454  KyFloat32 m_totalFlushTimeMs; // Time spend waiting for the Send queue to be emptied (either in NewFrame or in Flush, or even in CheckMemory)
455 
456  KyUInt32 m_sentBlobCountInFrame;
457  KyUInt32 m_sentBlobSizeInFrame;
458  KyUInt32 m_sentMessageCountInFrame;
459  KyUInt32 m_receivedMessageCountInFrame;
460 
461  UserBlobRegistry<SentBlobTypeStats> m_sentBlobTypeStatsRegistry;
462 
463  KyArray<VisualDebugStatGroup> m_statGroups;
464  bool m_enableAdvancedInternalStatistics;
465 
466  VisualDebugAttributesManager* m_visualDebugAttributesManager;
467  VisualDebugAttributeGroup* m_profilingVisualDebug;
468  VisualDebugAttributeGroup* m_advancedProfilingVisualDebug;
469 
470  bool m_messageProcessingIsPaused;
471 
472  // displayListBuilderRegistry, to verify that QueryBlobs have a DisplayListBuilder before sending them to the NavLab
473  Ptr<UserBlobRegistry<IDisplayListBuilder> > m_displayListBuilderRegistry;
474 };
475 
476 } // namespace Kaim
477 
478 #else
479 // Here we use a separated file in order to easily maintain both versions by comparing the two files (visualdebugserver.h and disabledvisualdebugserver.inl)
481 
482 // This allows to forward declare VisualDebugServer
483 // and to use DisabledVisualDebugServer separately in unit tests
484 namespace Kaim
485 {
486 
487 class VisualDebugServer : public DisabledVisualDebugServer
488 {
489 };
490 
491 }
492 #endif
493 
494 
DisconnectionMode
Define how to detect disconnections.
Definition: visualdebugserver.h:67
Base interface for a class that opens a file on disk.
Definition: fileopener.h:30
DisconnectionMode m_disconnectionMode
Define how to detect disconnections.
Definition: visualdebugserver.h:180
const char * m_localFileName
mandatory if m_mode = Mode_UseLocalFile.
Definition: visualdebugserver.h:162
std::uint32_t KyUInt32
uint32_t
Definition: types.h:29
use socket errors to detect disconnections (recommended)
Definition: visualdebugserver.h:68
KyUInt32 m_expectedKiloBytesPerFrame
Specifies the expected amount of memory to allocate per frame. Used to define size of a message...
Definition: visualdebugserver.h:175
String m_serverName
Associate a name to the server to ease identification of this server when connecting from the Navigat...
Definition: visualdebugserver.h:186
Writes all visual debug information to a file on the platform.
Definition: visualdebugserver.h:57
KyInt32 m_localFileMegaBytesLimit
The size limit of the local file, when this limit is reached, the VisualDebugServer disconnects...
Definition: visualdebugserver.h:168
Mode m_mode
The visual debug information destination mode.
Definition: visualdebugserver.h:142
#define KY_DEFINE_NEW_DELETE_OPERATORS(MemStat)
This macro defines new and delete operators.
Definition: memory.h:132
KyUInt32 m_maximumMegaBytes
Specifies the maximum amount of memory this VisualDebugServer is allowed to allocate for creating mes...
Definition: visualdebugserver.h:173
void SetMemoryConsumption(KyUInt32 expectedKiloBytesPerFrame, KyUInt32 maximumMegaBytesToUse)
Define memory limitations for the VisualDebugServer.
Definition: visualdebugserver.h:128
std::uint32_t UInt32
uint32_t
Definition: SF_Types.h:137
Configure the VisualDebugServer.
Definition: visualdebugserver.h:46
#define KY_DEPRECATED(expr)
The compiler issues a warning when a deprecated function or typedef is used.
Definition: types.h:93
Navigation return code class.
Definition: types.h:108
KyUInt32 m_broadcastPort
The port used to broadcast the existence of this server.
Definition: visualdebugserver.h:150
RunMode
Determine how the data are sent.
Definition: visualdebugserver.h:73
The Autodesk Navigation namespace.
Definition: gamekitcrowddispersion.cpp:17
run in current thread (recommended for most platforms)
Definition: visualdebugserver.h:74
Sends visual debug information to the NavigationLab over the Network.
Definition: visualdebugserver.h:56
KyUInt32 m_serverPort
The port used to listen to NavigationLab incoming connections.
Definition: visualdebugserver.h:147
use secondary threads for sending blobs
Definition: visualdebugserver.h:75
std::int32_t KyInt32
int32_t
Definition: types.h:24
FileOpenerBase * m_localFileOpener
if m_localFileOpener is NULL, DefaultFileOpener will be used
Definition: visualdebugserver.h:165
void UseNavigationLab(KyUInt32 serverPort=DefaultServerPort(), KyUInt32 broadcastPort=DefaultBroadcastPort(), MessageReceiverRegistry *navigationLabCommandHandlers=nullptr)
Reduce chances of selecting conflicting ports by looking at :
Definition: visualdebugserver.h:104
MessageReceiverRegistry * m_navigationLabCommandHandlers
Optional, handles the commands that come from the Autodesk Navigation from the Network.
Definition: visualdebugserver.h:157
Mode
Enumerates the visual debug information destination.
Definition: visualdebugserver.h:55
Start will block until a connection occurs.
Definition: visualdebugserver.h:63
#define KyUInt32MAXVAL
KyUInt32 max value
Definition: types.h:68
RunMode m_runMode
Define how to run the server, either directly in the current thread (recommended), or using secondary threads.
Definition: visualdebugserver.h:183
Start won't wait for a connection.
Definition: visualdebugserver.h:62
float KyFloat32
float
Definition: types.h:32
use heartbeat messages to detect disconnections (disconnection can occur when breakpointing) ...
Definition: visualdebugserver.h:69
WaitOnStart
Define the behavior for VisualDebugServer::Start.
Definition: visualdebugserver.h:61