0031642: Visualization - crash in Graphic3d_Structure::SetVisual() on redisplaying...
[occt.git] / src / Graphic3d / Graphic3d_FrameStats.cxx
CommitLineData
5e30547b 1// Copyright (c) 2017 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include <Graphic3d_FrameStats.hxx>
15
16#include <Graphic3d_CView.hxx>
17
18IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_FrameStats, Standard_Transient)
19
20namespace
21{
22 //! Format counter.
23 static std::ostream& formatCounter (std::ostream& theStream,
24 Standard_Integer theWidth,
25 const char* thePrefix,
26 Standard_Size theValue,
27 const char* thePostfix = NULL)
28 {
29 if (thePrefix != NULL)
30 {
31 theStream << thePrefix;
32 }
33 theStream << std::setfill(' ') << std::setw (theWidth);
34 if (theValue >= 1000000000)
35 {
36 Standard_Real aValM = Standard_Real(theValue) / 1000000000.0;
37 theStream << std::fixed << std::setprecision (1) << aValM << "G";
38 }
39 else if (theValue >= 1000000)
40 {
41 Standard_Real aValM = Standard_Real(theValue) / 1000000.0;
42 theStream << std::fixed << std::setprecision (1) << aValM << "M";
43 }
44 else if (theValue >= 1000)
45 {
46 Standard_Real aValK = Standard_Real(theValue) / 1000.0;
47 theStream << std::fixed << std::setprecision (1) << aValK << "k";
48 }
49 else
50 {
51 theStream << theValue;
52 }
53 if (thePostfix != NULL)
54 {
55 theStream << thePostfix;
56 }
57 return theStream;
58 }
59
60 //! Format memory counter.
61 static std::ostream& formatBytes (std::ostream& theStream,
62 Standard_Integer theWidth,
63 const char* thePrefix,
64 Standard_Size theValue,
65 const char* thePostfix = NULL)
66 {
67 if (thePrefix != NULL)
68 {
69 theStream << thePrefix;
70 }
71 theStream << std::setfill(' ') << std::setw (theWidth);
72 if (theValue >= 1024 * 1024 * 1024)
73 {
74 Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0 * 1024.0);
75 theStream << std::fixed << std::setprecision (1) << aValM << " GiB";
76 }
77 else if (theValue >= 1024 * 1024)
78 {
79 Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0);
80 theStream << std::fixed << std::setprecision (1) << aValM << " MiB";
81 }
82 else if (theValue >= 1024)
83 {
84 Standard_Real aValK = Standard_Real(theValue) / 1024.0;
85 theStream << std::fixed << std::setprecision (1) << aValK << " KiB";
86 }
87 else
88 {
89 theStream << theValue << " B";
90 }
91 if (thePostfix != NULL)
92 {
93 theStream << thePostfix;
94 }
95 return theStream;
96 }
97
98 static const Standard_Real THE_SECONDS_IN_HOUR = 3600.0;
99 static const Standard_Real THE_SECONDS_IN_MINUTE = 60.0;
100 static const Standard_Real THE_SECOND_IN_HOUR = 1.0 / THE_SECONDS_IN_HOUR;
101 static const Standard_Real THE_SECOND_IN_MINUTE = 1.0 / THE_SECONDS_IN_MINUTE;
102
103 //! Format time.
104 static std::ostream& formatTime (std::ostream& theStream,
105 Standard_Integer theWidth,
106 const char* thePrefix,
107 Standard_Real theSeconds,
108 const char* thePostfix = NULL)
109 {
110 if (thePrefix != NULL)
111 {
112 theStream << thePrefix;
113 }
114
115 Standard_Real aSecIn = theSeconds;
116 unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
117 aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
118 unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
119 aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
120 unsigned int aSeconds = (unsigned int )aSecIn;
121 aSecIn -= Standard_Real(aSeconds);
122 Standard_Real aMilliSeconds = 1000.0 * aSecIn;
123
124 char aBuffer[64];
125 theStream << std::setfill(' ') << std::setw (theWidth);
126 if (aHours > 0)
127 {
128 Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
129 theStream << aBuffer;
130 }
131 else if (aMinutes > 0)
132 {
133 Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
134 theStream << aBuffer;
135 }
136 else if (aSeconds > 0)
137 {
138 Sprintf (aBuffer, "%2u s", aSeconds);
139 theStream << aBuffer;
140 }
141 else
142 {
143 theStream << std::fixed << std::setprecision (1) << aMilliSeconds << " ms";
144 }
145
146 if (thePostfix != NULL)
147 {
148 theStream << thePostfix;
149 }
150 return theStream;
151 }
79b544e6 152
153 //! Add key-value pair to the dictionary.
154 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
155 const TCollection_AsciiString& theKey,
156 const char* theValue)
157 {
158 TCollection_AsciiString aValue (theValue != NULL ? theValue : "");
159 theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue;
160 }
161
162 //! Add key-value pair to the dictionary.
163 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
164 const TCollection_AsciiString& theKey,
165 const Standard_Real theValue)
166 {
167 char aTmp[50];
168 Sprintf (aTmp, "%.1g", theValue);
169 addInfo (theDict, theKey, aTmp);
170 }
171
172 //! Add key-value pair to the dictionary.
173 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
174 const TCollection_AsciiString& theKey,
175 const Standard_Size theValue)
176 {
177 char aTmp[50];
178 Sprintf (aTmp, "%zu", theValue);
179 addInfo (theDict, theKey, aTmp);
180 }
181
182 //! Format time.
183 static void addTimeInfo (TColStd_IndexedDataMapOfStringString& theDict,
184 const TCollection_AsciiString& theKey,
185 Standard_Real theSeconds)
186 {
187 Standard_Real aSecIn = theSeconds;
188 unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
189 aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
190 unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
191 aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
192 unsigned int aSeconds = (unsigned int )aSecIn;
193 aSecIn -= Standard_Real(aSeconds);
194 Standard_Real aMilliSeconds = 1000.0 * aSecIn;
195
196 char aBuffer[64];
197 if (aHours > 0)
198 {
199 Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
200 }
201 else if (aMinutes > 0)
202 {
203 Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
204 }
205 else if (aSeconds > 0)
206 {
207 Sprintf (aBuffer, "%2u", aSeconds);
208 }
209 else
210 {
211 addInfo (theDict, theKey, aMilliSeconds);
212 return;
213 }
214
215 addInfo (theDict, theKey, aBuffer);
216 }
5e30547b 217}
218
219// =======================================================================
220// function : Graphic3d_FrameStats
221// purpose :
222// =======================================================================
223Graphic3d_FrameStats::Graphic3d_FrameStats()
224: myFpsTimer (Standard_True),
225 myFrameStartTime (0.0),
226 myFrameDuration (0.0),
227 myUpdateInterval (1.0),
228 myFpsFrameCount (0),
229 myCounters (0, 0),
230 myLastFrameIndex (0),
231 myIsLongLineFormat (Standard_False)
232{
233 //
234}
235
236// =======================================================================
237// function : ~Graphic3d_FrameStats
238// purpose :
239// =======================================================================
240Graphic3d_FrameStats::~Graphic3d_FrameStats()
241{
242 //
243}
244
245// =======================================================================
246// function : FormatStats
247// purpose :
248// =======================================================================
249TCollection_AsciiString Graphic3d_FrameStats::FormatStats (Graphic3d_RenderingParams::PerfCounters theFlags) const
250{
251 const Standard_Integer aValWidth = 5;
252 std::stringstream aBuf;
253 const Standard_Boolean isCompact = theFlags == Graphic3d_RenderingParams::PerfCounters_FrameRate; // only FPS is displayed
254 const Graphic3d_FrameStatsData& aStats = LastDataFrame();
255 if (myIsLongLineFormat
256 && (theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0
257 && (theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
258 {
259 aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 9) << std::fixed << std::setprecision (1) << aStats.FrameRate()
260 << " [CPU: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 10) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu() << "]\n";
261 }
262 else
263 {
264 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
265 {
266 aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRate() << "\n";
267 }
268 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
269 {
270 aBuf << "CPU FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu() << "\n";
271 }
272 }
273 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
274 {
275 if (myIsLongLineFormat)
276 {
277 formatCounter (aBuf, aValWidth, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
278 if (HasCulledLayers())
279 {
280 formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled], "]");
281 }
282 aBuf << "\n";
283 }
284 else
285 {
286 formatCounter (aBuf, aValWidth + 3, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers], "\n");
287 }
288 }
289 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
290 {
291 if (myIsLongLineFormat)
292 {
293 formatCounter (aBuf, aValWidth, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
294 if (HasCulledStructs())
295 {
296 formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled], "]");
297 }
298 aBuf << "\n";
299 }
300 else
301 {
302 formatCounter (aBuf, aValWidth + 3, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs], "\n");
303 }
304 }
305 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0
306 || (theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0
307 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
b9f43ad1 308 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0
5e30547b 309 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0
310 || (!myIsLongLineFormat
311 && ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0
312 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)))
313 {
314 aBuf << "Rendered\n";
315 }
316 if (!myIsLongLineFormat
317 && (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
318 {
319 formatCounter (aBuf, aValWidth, " Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled], "\n");
320 }
321 if (!myIsLongLineFormat
322 && (theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
323 {
324 formatCounter (aBuf, aValWidth, " Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled], "\n");
325 }
326 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
327 {
328 formatCounter (aBuf, aValWidth, " Groups: ", aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled], "\n");
329 }
330 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
331 {
332 formatCounter (aBuf, aValWidth, " Arrays: ", aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled], "\n");
333 formatCounter (aBuf, aValWidth, " [fill]: ", aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled], "\n");
334 formatCounter (aBuf, aValWidth, " [line]: ", aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled], "\n");
335 formatCounter (aBuf, aValWidth, " [point]: ", aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled], "\n");
336 formatCounter (aBuf, aValWidth, " [text]: ", aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled], "\n");
337 }
338 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
339 {
340 formatCounter (aBuf, aValWidth, " Triangles: ", aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled], "\n");
341 }
b9f43ad1 342 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
343 {
344 formatCounter (aBuf, aValWidth, " Lines: ", aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled], "\n");
345 }
5e30547b 346 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
347 {
348 formatCounter (aBuf, aValWidth, " Points: ", aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled], "\n");
349 }
350 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
351 {
352 aBuf << "GPU Memory\n";
353 formatBytes (aBuf, aValWidth, " Geometry: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom], "\n");
354 formatBytes (aBuf, aValWidth, " Textures: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures], "\n");
355 formatBytes (aBuf, aValWidth, " Frames: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos], "\n");
356 }
357
358 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
359 {
360 aBuf << "Timers Average\n";
361 formatTime (aBuf, aValWidth, " Elapsed Frame: ", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame], "\n");
362 formatTime (aBuf, aValWidth, " CPU Frame: ", aStats[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
363 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
364 {
365 formatTime (aBuf, aValWidth, " CPU Picking: ", aStats[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
366 }
367 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
368 {
369 formatTime (aBuf, aValWidth, " CPU Culling: ", aStats[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
370 }
371 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
372 {
373 formatTime (aBuf, aValWidth, " CPU Dynamics: ", aStats[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
374 }
375 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
376 {
377 aBuf << "Timers Max\n";
378 formatTime (aBuf, aValWidth, " CPU Frame: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
379 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
380 {
381 formatTime (aBuf, aValWidth, " CPU Picking: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
382 }
383 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
384 {
385 formatTime (aBuf, aValWidth, " CPU Culling: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
386 }
387 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
388 {
389 formatTime (aBuf, aValWidth, " CPU Dynamics: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
390 }
391 }
392 }
393
394 return TCollection_AsciiString (aBuf.str().c_str());
395}
396
79b544e6 397// =======================================================================
398// function : FormatStats
399// purpose :
400// =======================================================================
401void Graphic3d_FrameStats::FormatStats (TColStd_IndexedDataMapOfStringString& theDict,
402 Graphic3d_RenderingParams::PerfCounters theFlags) const
403{
404 const Graphic3d_FrameStatsData& aStats = LastDataFrame();
405 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
406 {
407 addInfo (theDict, "FPS", aStats.FrameRate());
408 }
409 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
410 {
411 addInfo (theDict, "CPU FPS", aStats.FrameRateCpu());
412 }
413 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
414 {
415 addInfo (theDict, "Layers", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
416 if (HasCulledLayers())
417 {
418 addInfo (theDict, "Rendered layers", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled]);
419 }
420 }
421 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
422 {
423 addInfo (theDict, "Structs", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
424 if (HasCulledStructs())
425 {
426 addInfo (theDict, "Rendered structs", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled]);
427 }
428 }
429 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
430 {
431 addInfo (theDict, "Rendered groups", aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled]);
432 }
433 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
434 {
435 addInfo (theDict, "Rendered arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled]);
436 addInfo (theDict, "Rendered [fill] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled]);
437 addInfo (theDict, "Rendered [line] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled]);
438 addInfo (theDict, "Rendered [point] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled]);
439 addInfo (theDict, "Rendered [text] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]);
440 }
441 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
442 {
443 addInfo (theDict, "Rendered triangles", aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled]);
444 }
b9f43ad1 445 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
446 {
447 addInfo (theDict, "Rendered lines", aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled]);
448 }
79b544e6 449 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
450 {
451 addInfo (theDict, "Rendered points", aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled]);
452 }
453 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
454 {
455 addInfo (theDict, "GPU Memory [geometry]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom]);
456 addInfo (theDict, "GPU Memory [textures]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures]);
457 addInfo (theDict, "GPU Memory [frames]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos]);
458 }
459
460 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
461 {
462 addTimeInfo (theDict, "Elapsed Frame (average)", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame]);
463 addTimeInfo (theDict, "CPU Frame (average)", aStats[Graphic3d_FrameStatsTimer_CpuFrame]);
464 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
465 {
466 addTimeInfo (theDict, "CPU Picking (average)", aStats[Graphic3d_FrameStatsTimer_CpuPicking]);
467 }
468 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
469 {
470 addTimeInfo (theDict, "CPU Culling (average)", aStats[Graphic3d_FrameStatsTimer_CpuCulling]);
471 }
472 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
473 {
474 addTimeInfo (theDict, "CPU Dynamics (average)", aStats[Graphic3d_FrameStatsTimer_CpuDynamics]);
475 }
476 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
477 {
478 addTimeInfo (theDict, "CPU Frame (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame]);
479 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
480 {
481 addTimeInfo (theDict, "CPU Picking (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking]);
482 }
483 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
484 {
485 addTimeInfo (theDict, "CPU Culling (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling]);
486 }
487 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
488 {
489 addTimeInfo (theDict, "CPU Dynamics (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics]);
490 }
491 }
492 }
493}
494
5e30547b 495// =======================================================================
496// function : FrameStart
497// purpose :
498// =======================================================================
499void Graphic3d_FrameStats::FrameStart (const Handle(Graphic3d_CView)& theView,
500 bool theIsImmediateOnly)
501{
502 const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
503 ? theView->RenderingParams().CollectedStats
504 : Graphic3d_RenderingParams::PerfCounters_NONE;
505 if (theIsImmediateOnly
506 && (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
507 {
508 return;
509 }
510
511 const Standard_Integer aNbFrames = Max (!theView.IsNull()
512 ? theView->RenderingParams().StatsNbFrames
513 : 1, 1);
514 if (myCounters.Size() != aNbFrames)
515 {
516 myCounters.Resize (0, aNbFrames - 1, false);
517 myCounters.Init (Graphic3d_FrameStatsData());
518 myLastFrameIndex = myCounters.Upper();
519 }
520
521 // reset values at the end of frame (after data has been flushed),
522 // so that application can put some counters (like picking time) before FrameStart().
523 //myCountersTmp.Reset();
524
525 myFrameStartTime = myFpsTimer.ElapsedTime();
526 if (!myFpsTimer.IsStarted())
527 {
528 myFpsTimer.Reset();
529 myFpsTimer.Start();
530 myFpsFrameCount = 0;
531 }
532}
533
534// =======================================================================
535// function : FrameEnd
536// purpose :
537// =======================================================================
538void Graphic3d_FrameStats::FrameEnd (const Handle(Graphic3d_CView)& theView,
539 bool theIsImmediateOnly)
540{
541 const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
542 ? theView->RenderingParams().CollectedStats
543 : Graphic3d_RenderingParams::PerfCounters_NONE;
544 if (theIsImmediateOnly
545 && (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
546 {
547 return;
548 }
549
550 const double aTime = myFpsTimer.ElapsedTime();
551 myFrameDuration = aTime - myFrameStartTime;
552 ++myFpsFrameCount;
553 if (!theView.IsNull())
554 {
555 myUpdateInterval = theView->RenderingParams().StatsUpdateInterval;
556 }
557
558 if (aTime < myUpdateInterval)
559 {
560 myCountersTmp.FlushTimers (myFpsFrameCount, false);
561 return;
562 }
563
564 if (aTime > gp::Resolution())
565 {
566 // update FPS
567 myFpsTimer.Stop();
568 const double aCpuSec = myFpsTimer.UserTimeCPU();
569
570 myCountersTmp[Graphic3d_FrameStatsTimer_ElapsedFrame] = aTime;
571 myCountersTmp[Graphic3d_FrameStatsTimer_CpuFrame] = aCpuSec;
572 myCountersTmp.ChangeFrameRate() = double(myFpsFrameCount) / aTime;
573 myCountersTmp.ChangeFrameRateCpu() = aCpuSec > gp::Resolution()
574 ? double(myFpsFrameCount) / aCpuSec
575 : -1.0;
576 myCountersTmp.FlushTimers (myFpsFrameCount, true);
577 myCountersMax.FillMax (myCountersTmp);
578 myFpsTimer.Reset();
579 myFpsTimer.Start();
580 myFpsFrameCount = 0;
581 }
582
583 // update structure counters
584 if (theView.IsNull())
585 {
586 myCounters.SetValue (myLastFrameIndex, myCountersTmp);
587 myCountersTmp.Reset();
588 return;
589 }
590
591 updateStatistics (theView, theIsImmediateOnly);
592
593 if (++myLastFrameIndex > myCounters.Upper())
594 {
595 myLastFrameIndex = myCounters.Lower();
596 }
597 myCounters.SetValue (myLastFrameIndex, myCountersTmp);
598 myCountersTmp.Reset();
599}