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 | |
18 | IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_FrameStats, Standard_Transient) |
19 | |
20 | namespace |
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 | // ======================================================================= |
223 | Graphic3d_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 | // ======================================================================= |
240 | Graphic3d_FrameStats::~Graphic3d_FrameStats() |
241 | { |
242 | // |
243 | } |
244 | |
245 | // ======================================================================= |
246 | // function : FormatStats |
247 | // purpose : |
248 | // ======================================================================= |
249 | TCollection_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 | // ======================================================================= |
401 | void 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 | // ======================================================================= |
499 | void 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 | // ======================================================================= |
538 | void 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 | } |