0031687: Draw Harness, ViewerTest - extend command vrenderparams with option updating...
[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;
8f5760bc 52 if (thePostfix == NULL)
53 {
54 theStream << " ";
55 }
5e30547b 56 }
57 if (thePostfix != NULL)
58 {
59 theStream << thePostfix;
60 }
61 return theStream;
62 }
63
8f5760bc 64 //! Format a pair of counters.
65 static std::ostream& formatCounterPair (std::ostream& theStream,
66 Standard_Integer theWidth,
67 const char* thePrefix,
68 Standard_Size theValue,
69 Standard_Size theImmValue,
70 bool theToShowImmediate)
71 {
72 formatCounter (theStream, theWidth, thePrefix, theValue, NULL);
73 if (theToShowImmediate)
74 {
75 formatCounter (theStream, 1, "(", theImmValue, ")");
76 }
77 theStream << "\n";
78 return theStream;
79 }
80
5e30547b 81 //! Format memory counter.
82 static std::ostream& formatBytes (std::ostream& theStream,
83 Standard_Integer theWidth,
84 const char* thePrefix,
85 Standard_Size theValue,
86 const char* thePostfix = NULL)
87 {
88 if (thePrefix != NULL)
89 {
90 theStream << thePrefix;
91 }
92 theStream << std::setfill(' ') << std::setw (theWidth);
93 if (theValue >= 1024 * 1024 * 1024)
94 {
95 Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0 * 1024.0);
96 theStream << std::fixed << std::setprecision (1) << aValM << " GiB";
97 }
98 else if (theValue >= 1024 * 1024)
99 {
100 Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0);
101 theStream << std::fixed << std::setprecision (1) << aValM << " MiB";
102 }
103 else if (theValue >= 1024)
104 {
105 Standard_Real aValK = Standard_Real(theValue) / 1024.0;
106 theStream << std::fixed << std::setprecision (1) << aValK << " KiB";
107 }
108 else
109 {
110 theStream << theValue << " B";
111 }
112 if (thePostfix != NULL)
113 {
114 theStream << thePostfix;
115 }
116 return theStream;
117 }
118
119 static const Standard_Real THE_SECONDS_IN_HOUR = 3600.0;
120 static const Standard_Real THE_SECONDS_IN_MINUTE = 60.0;
121 static const Standard_Real THE_SECOND_IN_HOUR = 1.0 / THE_SECONDS_IN_HOUR;
122 static const Standard_Real THE_SECOND_IN_MINUTE = 1.0 / THE_SECONDS_IN_MINUTE;
123
124 //! Format time.
125 static std::ostream& formatTime (std::ostream& theStream,
126 Standard_Integer theWidth,
127 const char* thePrefix,
128 Standard_Real theSeconds,
129 const char* thePostfix = NULL)
130 {
131 if (thePrefix != NULL)
132 {
133 theStream << thePrefix;
134 }
135
136 Standard_Real aSecIn = theSeconds;
137 unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
138 aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
139 unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
140 aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
141 unsigned int aSeconds = (unsigned int )aSecIn;
142 aSecIn -= Standard_Real(aSeconds);
143 Standard_Real aMilliSeconds = 1000.0 * aSecIn;
144
145 char aBuffer[64];
146 theStream << std::setfill(' ') << std::setw (theWidth);
147 if (aHours > 0)
148 {
149 Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
150 theStream << aBuffer;
151 }
152 else if (aMinutes > 0)
153 {
154 Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
155 theStream << aBuffer;
156 }
157 else if (aSeconds > 0)
158 {
159 Sprintf (aBuffer, "%2u s", aSeconds);
160 theStream << aBuffer;
161 }
162 else
163 {
164 theStream << std::fixed << std::setprecision (1) << aMilliSeconds << " ms";
165 }
166
167 if (thePostfix != NULL)
168 {
169 theStream << thePostfix;
170 }
171 return theStream;
172 }
79b544e6 173
174 //! Add key-value pair to the dictionary.
175 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
176 const TCollection_AsciiString& theKey,
177 const char* theValue)
178 {
179 TCollection_AsciiString aValue (theValue != NULL ? theValue : "");
180 theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue;
181 }
182
183 //! Add key-value pair to the dictionary.
184 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
185 const TCollection_AsciiString& theKey,
186 const Standard_Real theValue)
187 {
188 char aTmp[50];
189 Sprintf (aTmp, "%.1g", theValue);
190 addInfo (theDict, theKey, aTmp);
191 }
192
193 //! Add key-value pair to the dictionary.
194 static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
195 const TCollection_AsciiString& theKey,
196 const Standard_Size theValue)
197 {
198 char aTmp[50];
199 Sprintf (aTmp, "%zu", theValue);
200 addInfo (theDict, theKey, aTmp);
201 }
202
203 //! Format time.
204 static void addTimeInfo (TColStd_IndexedDataMapOfStringString& theDict,
205 const TCollection_AsciiString& theKey,
206 Standard_Real theSeconds)
207 {
208 Standard_Real aSecIn = theSeconds;
209 unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
210 aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
211 unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
212 aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
213 unsigned int aSeconds = (unsigned int )aSecIn;
214 aSecIn -= Standard_Real(aSeconds);
215 Standard_Real aMilliSeconds = 1000.0 * aSecIn;
216
217 char aBuffer[64];
218 if (aHours > 0)
219 {
220 Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
221 }
222 else if (aMinutes > 0)
223 {
224 Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
225 }
226 else if (aSeconds > 0)
227 {
228 Sprintf (aBuffer, "%2u", aSeconds);
229 }
230 else
231 {
232 addInfo (theDict, theKey, aMilliSeconds);
233 return;
234 }
235
236 addInfo (theDict, theKey, aBuffer);
237 }
5e30547b 238}
239
240// =======================================================================
241// function : Graphic3d_FrameStats
242// purpose :
243// =======================================================================
244Graphic3d_FrameStats::Graphic3d_FrameStats()
245: myFpsTimer (Standard_True),
246 myFrameStartTime (0.0),
247 myFrameDuration (0.0),
248 myUpdateInterval (1.0),
249 myFpsFrameCount (0),
250 myCounters (0, 0),
251 myLastFrameIndex (0),
252 myIsLongLineFormat (Standard_False)
253{
254 //
255}
256
257// =======================================================================
258// function : ~Graphic3d_FrameStats
259// purpose :
260// =======================================================================
261Graphic3d_FrameStats::~Graphic3d_FrameStats()
262{
263 //
264}
265
266// =======================================================================
267// function : FormatStats
268// purpose :
269// =======================================================================
270TCollection_AsciiString Graphic3d_FrameStats::FormatStats (Graphic3d_RenderingParams::PerfCounters theFlags) const
271{
272 const Standard_Integer aValWidth = 5;
273 std::stringstream aBuf;
274 const Standard_Boolean isCompact = theFlags == Graphic3d_RenderingParams::PerfCounters_FrameRate; // only FPS is displayed
275 const Graphic3d_FrameStatsData& aStats = LastDataFrame();
276 if (myIsLongLineFormat
277 && (theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0
278 && (theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
279 {
280 aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 9) << std::fixed << std::setprecision (1) << aStats.FrameRate()
281 << " [CPU: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 10) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu() << "]\n";
282 }
283 else
284 {
285 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
286 {
8f5760bc 287 aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRate();
288 if (aStats.ImmediateFrameRate() > 0.0)
289 {
290 aBuf << " (" << std::fixed << std::setprecision (1) << aStats.ImmediateFrameRate() << ")";
291 }
292 aBuf << "\n";
5e30547b 293 }
294 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
295 {
8f5760bc 296 aBuf << "CPU FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu();
297 if (aStats.ImmediateFrameRateCpu() > 0.0)
298 {
299 aBuf << " (" << std::fixed << std::setprecision (1) << aStats.ImmediateFrameRateCpu() << ")";
300 }
301 aBuf << "\n";
5e30547b 302 }
303 }
304 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
305 {
306 if (myIsLongLineFormat)
307 {
308 formatCounter (aBuf, aValWidth, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
309 if (HasCulledLayers())
310 {
311 formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled], "]");
312 }
313 aBuf << "\n";
314 }
315 else
316 {
317 formatCounter (aBuf, aValWidth + 3, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers], "\n");
318 }
319 }
320 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
321 {
322 if (myIsLongLineFormat)
323 {
324 formatCounter (aBuf, aValWidth, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
325 if (HasCulledStructs())
326 {
327 formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled], "]");
328 }
329 aBuf << "\n";
330 }
331 else
332 {
333 formatCounter (aBuf, aValWidth + 3, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs], "\n");
334 }
335 }
8f5760bc 336
337 const bool hasImmediate = aStats[Graphic3d_FrameStatsCounter_NbLayersImmediate] != 0 || aStats.ImmediateFrameRate() > 0.0;
5e30547b 338 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0
339 || (theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0
340 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
b9f43ad1 341 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0
5e30547b 342 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0
343 || (!myIsLongLineFormat
344 && ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0
345 || (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)))
346 {
8f5760bc 347 if (hasImmediate)
348 {
349 aBuf << "Rendered (imm.)\n";
350 }
351 else
352 {
353 aBuf << "Rendered\n";
354 }
5e30547b 355 }
356 if (!myIsLongLineFormat
357 && (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
358 {
8f5760bc 359 formatCounterPair (aBuf, aValWidth, " Layers: ",
360 aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled],
361 aStats[Graphic3d_FrameStatsCounter_NbLayersImmediate], hasImmediate);
5e30547b 362 }
363 if (!myIsLongLineFormat
364 && (theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
365 {
8f5760bc 366 formatCounterPair (aBuf, aValWidth, " Structs: ",
367 aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled],
368 aStats[Graphic3d_FrameStatsCounter_NbStructsImmediate], hasImmediate);
5e30547b 369 }
370 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
371 {
8f5760bc 372 formatCounterPair (aBuf, aValWidth, " Groups: ",
373 aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled],
374 aStats[Graphic3d_FrameStatsCounter_NbGroupsImmediate], hasImmediate);
5e30547b 375 }
376 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
377 {
8f5760bc 378 formatCounterPair (aBuf, aValWidth, " Arrays: ",
379 aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled],
380 aStats[Graphic3d_FrameStatsCounter_NbElemsImmediate], hasImmediate);
381 formatCounterPair (aBuf, aValWidth, " [fill]: ",
382 aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled],
383 aStats[Graphic3d_FrameStatsCounter_NbElemsFillImmediate], hasImmediate);
384 formatCounterPair (aBuf, aValWidth, " [line]: ",
385 aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled],
386 aStats[Graphic3d_FrameStatsCounter_NbElemsLineImmediate], hasImmediate);
387 formatCounterPair (aBuf, aValWidth, " [point]: ",
388 aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled],
389 aStats[Graphic3d_FrameStatsCounter_NbElemsPointImmediate], hasImmediate);
390 formatCounterPair (aBuf, aValWidth, " [text]: ",
391 aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled],
392 aStats[Graphic3d_FrameStatsCounter_NbElemsTextImmediate], hasImmediate);
5e30547b 393 }
394 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
395 {
8f5760bc 396 formatCounterPair (aBuf, aValWidth, " Triangles: ",
397 aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled],
398 aStats[Graphic3d_FrameStatsCounter_NbTrianglesImmediate], hasImmediate);
5e30547b 399 }
b9f43ad1 400 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
401 {
8f5760bc 402 formatCounterPair (aBuf, aValWidth, " Lines: ",
403 aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled],
404 aStats[Graphic3d_FrameStatsCounter_NbLinesImmediate], hasImmediate);
b9f43ad1 405 }
5e30547b 406 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
407 {
8f5760bc 408 formatCounterPair (aBuf, aValWidth, " Points: ",
409 aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled],
410 aStats[Graphic3d_FrameStatsCounter_NbPointsImmediate], hasImmediate);
5e30547b 411 }
412 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
413 {
414 aBuf << "GPU Memory\n";
415 formatBytes (aBuf, aValWidth, " Geometry: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom], "\n");
416 formatBytes (aBuf, aValWidth, " Textures: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures], "\n");
417 formatBytes (aBuf, aValWidth, " Frames: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos], "\n");
418 }
419
420 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
421 {
422 aBuf << "Timers Average\n";
423 formatTime (aBuf, aValWidth, " Elapsed Frame: ", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame], "\n");
424 formatTime (aBuf, aValWidth, " CPU Frame: ", aStats[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
425 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
426 {
427 formatTime (aBuf, aValWidth, " CPU Picking: ", aStats[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
428 }
429 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
430 {
431 formatTime (aBuf, aValWidth, " CPU Culling: ", aStats[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
432 }
433 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
434 {
435 formatTime (aBuf, aValWidth, " CPU Dynamics: ", aStats[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
436 }
437 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
438 {
439 aBuf << "Timers Max\n";
440 formatTime (aBuf, aValWidth, " CPU Frame: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
441 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
442 {
443 formatTime (aBuf, aValWidth, " CPU Picking: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
444 }
445 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
446 {
447 formatTime (aBuf, aValWidth, " CPU Culling: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
448 }
449 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
450 {
451 formatTime (aBuf, aValWidth, " CPU Dynamics: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
452 }
453 }
454 }
455
456 return TCollection_AsciiString (aBuf.str().c_str());
457}
458
79b544e6 459// =======================================================================
460// function : FormatStats
461// purpose :
462// =======================================================================
463void Graphic3d_FrameStats::FormatStats (TColStd_IndexedDataMapOfStringString& theDict,
464 Graphic3d_RenderingParams::PerfCounters theFlags) const
465{
466 const Graphic3d_FrameStatsData& aStats = LastDataFrame();
467 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
468 {
469 addInfo (theDict, "FPS", aStats.FrameRate());
470 }
471 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
472 {
473 addInfo (theDict, "CPU FPS", aStats.FrameRateCpu());
474 }
475 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
476 {
477 addInfo (theDict, "Layers", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
478 if (HasCulledLayers())
479 {
480 addInfo (theDict, "Rendered layers", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled]);
481 }
482 }
483 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
484 {
485 addInfo (theDict, "Structs", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
486 if (HasCulledStructs())
487 {
488 addInfo (theDict, "Rendered structs", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled]);
489 }
490 }
491 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
492 {
493 addInfo (theDict, "Rendered groups", aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled]);
494 }
495 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
496 {
497 addInfo (theDict, "Rendered arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled]);
498 addInfo (theDict, "Rendered [fill] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled]);
499 addInfo (theDict, "Rendered [line] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled]);
500 addInfo (theDict, "Rendered [point] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled]);
501 addInfo (theDict, "Rendered [text] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]);
502 }
503 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
504 {
505 addInfo (theDict, "Rendered triangles", aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled]);
506 }
b9f43ad1 507 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
508 {
509 addInfo (theDict, "Rendered lines", aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled]);
510 }
79b544e6 511 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
512 {
513 addInfo (theDict, "Rendered points", aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled]);
514 }
515 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
516 {
517 addInfo (theDict, "GPU Memory [geometry]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom]);
518 addInfo (theDict, "GPU Memory [textures]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures]);
519 addInfo (theDict, "GPU Memory [frames]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos]);
520 }
521
522 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
523 {
524 addTimeInfo (theDict, "Elapsed Frame (average)", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame]);
525 addTimeInfo (theDict, "CPU Frame (average)", aStats[Graphic3d_FrameStatsTimer_CpuFrame]);
526 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
527 {
528 addTimeInfo (theDict, "CPU Picking (average)", aStats[Graphic3d_FrameStatsTimer_CpuPicking]);
529 }
530 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
531 {
532 addTimeInfo (theDict, "CPU Culling (average)", aStats[Graphic3d_FrameStatsTimer_CpuCulling]);
533 }
534 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
535 {
536 addTimeInfo (theDict, "CPU Dynamics (average)", aStats[Graphic3d_FrameStatsTimer_CpuDynamics]);
537 }
538 if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
539 {
540 addTimeInfo (theDict, "CPU Frame (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame]);
541 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
542 {
543 addTimeInfo (theDict, "CPU Picking (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking]);
544 }
545 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
546 {
547 addTimeInfo (theDict, "CPU Culling (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling]);
548 }
549 if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
550 {
551 addTimeInfo (theDict, "CPU Dynamics (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics]);
552 }
553 }
554 }
555}
556
5e30547b 557// =======================================================================
558// function : FrameStart
559// purpose :
560// =======================================================================
561void Graphic3d_FrameStats::FrameStart (const Handle(Graphic3d_CView)& theView,
562 bool theIsImmediateOnly)
563{
564 const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
565 ? theView->RenderingParams().CollectedStats
566 : Graphic3d_RenderingParams::PerfCounters_NONE;
567 if (theIsImmediateOnly
568 && (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
569 {
570 return;
571 }
572
573 const Standard_Integer aNbFrames = Max (!theView.IsNull()
574 ? theView->RenderingParams().StatsNbFrames
575 : 1, 1);
576 if (myCounters.Size() != aNbFrames)
577 {
578 myCounters.Resize (0, aNbFrames - 1, false);
579 myCounters.Init (Graphic3d_FrameStatsData());
580 myLastFrameIndex = myCounters.Upper();
581 }
582
583 // reset values at the end of frame (after data has been flushed),
584 // so that application can put some counters (like picking time) before FrameStart().
585 //myCountersTmp.Reset();
586
587 myFrameStartTime = myFpsTimer.ElapsedTime();
588 if (!myFpsTimer.IsStarted())
589 {
590 myFpsTimer.Reset();
591 myFpsTimer.Start();
592 myFpsFrameCount = 0;
593 }
594}
595
596// =======================================================================
597// function : FrameEnd
598// purpose :
599// =======================================================================
600void Graphic3d_FrameStats::FrameEnd (const Handle(Graphic3d_CView)& theView,
601 bool theIsImmediateOnly)
602{
603 const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
604 ? theView->RenderingParams().CollectedStats
605 : Graphic3d_RenderingParams::PerfCounters_NONE;
606 if (theIsImmediateOnly
607 && (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
608 {
609 return;
610 }
611
612 const double aTime = myFpsTimer.ElapsedTime();
613 myFrameDuration = aTime - myFrameStartTime;
614 ++myFpsFrameCount;
615 if (!theView.IsNull())
616 {
617 myUpdateInterval = theView->RenderingParams().StatsUpdateInterval;
618 }
619
620 if (aTime < myUpdateInterval)
621 {
622 myCountersTmp.FlushTimers (myFpsFrameCount, false);
623 return;
624 }
625
8f5760bc 626 const Graphic3d_FrameStatsData& aPrevFrame = myCounters.Value (myLastFrameIndex);
5e30547b 627 if (aTime > gp::Resolution())
628 {
629 // update FPS
630 myFpsTimer.Stop();
631 const double aCpuSec = myFpsTimer.UserTimeCPU();
5e30547b 632 myCountersTmp[Graphic3d_FrameStatsTimer_ElapsedFrame] = aTime;
633 myCountersTmp[Graphic3d_FrameStatsTimer_CpuFrame] = aCpuSec;
8f5760bc 634
635 if (theIsImmediateOnly)
636 {
637 myCountersTmp.ChangeImmediateFrameRate() = double(myFpsFrameCount) / aTime;
638 myCountersTmp.ChangeImmediateFrameRateCpu() = aCpuSec > gp::Resolution()
639 ? double(myFpsFrameCount) / aCpuSec
640 : -1.0;
641 myCountersTmp.ChangeFrameRate() = aPrevFrame.FrameRate();
642 myCountersTmp.ChangeFrameRateCpu() = aPrevFrame.FrameRateCpu();
643 }
644 else
645 {
646 myCountersTmp.ChangeImmediateFrameRate() = -1.0;
647 myCountersTmp.ChangeImmediateFrameRateCpu() = -1.0;
648 myCountersTmp.ChangeFrameRate() = double(myFpsFrameCount) / aTime;
649 myCountersTmp.ChangeFrameRateCpu() = aCpuSec > gp::Resolution()
650 ? double(myFpsFrameCount) / aCpuSec
651 : -1.0;
652 }
5e30547b 653 myCountersTmp.FlushTimers (myFpsFrameCount, true);
654 myCountersMax.FillMax (myCountersTmp);
655 myFpsTimer.Reset();
656 myFpsTimer.Start();
657 myFpsFrameCount = 0;
658 }
659
660 // update structure counters
661 if (theView.IsNull())
662 {
663 myCounters.SetValue (myLastFrameIndex, myCountersTmp);
664 myCountersTmp.Reset();
665 return;
666 }
667
668 updateStatistics (theView, theIsImmediateOnly);
669
670 if (++myLastFrameIndex > myCounters.Upper())
671 {
672 myLastFrameIndex = myCounters.Lower();
673 }
8f5760bc 674 if (theIsImmediateOnly)
675 {
676 // copy rendered counters collected for immediate layers
677 const Standard_Integer anImmShift = Graphic3d_FrameStatsCounter_IMMEDIATE_LOWER - Graphic3d_FrameStatsCounter_RENDERED_LOWER;
678 Standard_STATIC_ASSERT((Graphic3d_FrameStatsCounter_RENDERED_UPPER - Graphic3d_FrameStatsCounter_RENDERED_LOWER) == (Graphic3d_FrameStatsCounter_IMMEDIATE_UPPER - Graphic3d_FrameStatsCounter_IMMEDIATE_LOWER))
679 for (Standard_Integer aCntIter = Graphic3d_FrameStatsCounter_RENDERED_LOWER; aCntIter <= Graphic3d_FrameStatsCounter_RENDERED_UPPER; ++aCntIter)
680 {
681 myCountersTmp.ChangeCounterValue ((Graphic3d_FrameStatsCounter )(aCntIter + anImmShift)) = myCountersTmp.CounterValue ((Graphic3d_FrameStatsCounter )aCntIter);
682 }
683
684 // copy main rendered counters from previous non-immediate frame
685 for (Standard_Integer aCntIter = Graphic3d_FrameStatsCounter_RENDERED_LOWER; aCntIter <= Graphic3d_FrameStatsCounter_RENDERED_UPPER; ++aCntIter)
686 {
687 myCountersTmp.ChangeCounterValue ((Graphic3d_FrameStatsCounter )aCntIter) = aPrevFrame.CounterValue ((Graphic3d_FrameStatsCounter )aCntIter);
688 }
689 myCountersTmp.ChangeCounterValue (Graphic3d_FrameStatsCounter_EstimatedBytesGeom) = aPrevFrame.CounterValue (Graphic3d_FrameStatsCounter_EstimatedBytesGeom);
690 }
5e30547b 691 myCounters.SetValue (myLastFrameIndex, myCountersTmp);
692 myCountersTmp.Reset();
693}