1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-06-20 11:54:07 +03:00
occt/src/Graphic3d/Graphic3d_FrameStats.cxx

694 lines
27 KiB
C++

// Copyright (c) 2017 OPEN CASCADE SAS
//
// This file is part of Open CASCADE Technology software library.
//
// This library is free software; you can redistribute it and/or modify it under
// the terms of the GNU Lesser General Public License version 2.1 as published
// by the Free Software Foundation, with special exception defined in the file
// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
// distribution for complete text of the license and disclaimer of any warranty.
//
// Alternatively, this file may be used under the terms of Open CASCADE
// commercial license or contractual agreement.
#include <Graphic3d_FrameStats.hxx>
#include <Graphic3d_CView.hxx>
IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_FrameStats, Standard_Transient)
namespace
{
//! Format counter.
static std::ostream& formatCounter (std::ostream& theStream,
Standard_Integer theWidth,
const char* thePrefix,
Standard_Size theValue,
const char* thePostfix = NULL)
{
if (thePrefix != NULL)
{
theStream << thePrefix;
}
theStream << std::setfill(' ') << std::setw (theWidth);
if (theValue >= 1000000000)
{
Standard_Real aValM = Standard_Real(theValue) / 1000000000.0;
theStream << std::fixed << std::setprecision (1) << aValM << "G";
}
else if (theValue >= 1000000)
{
Standard_Real aValM = Standard_Real(theValue) / 1000000.0;
theStream << std::fixed << std::setprecision (1) << aValM << "M";
}
else if (theValue >= 1000)
{
Standard_Real aValK = Standard_Real(theValue) / 1000.0;
theStream << std::fixed << std::setprecision (1) << aValK << "k";
}
else
{
theStream << theValue;
if (thePostfix == NULL)
{
theStream << " ";
}
}
if (thePostfix != NULL)
{
theStream << thePostfix;
}
return theStream;
}
//! Format a pair of counters.
static std::ostream& formatCounterPair (std::ostream& theStream,
Standard_Integer theWidth,
const char* thePrefix,
Standard_Size theValue,
Standard_Size theImmValue,
bool theToShowImmediate)
{
formatCounter (theStream, theWidth, thePrefix, theValue, NULL);
if (theToShowImmediate)
{
formatCounter (theStream, 1, "(", theImmValue, ")");
}
theStream << "\n";
return theStream;
}
//! Format memory counter.
static std::ostream& formatBytes (std::ostream& theStream,
Standard_Integer theWidth,
const char* thePrefix,
Standard_Size theValue,
const char* thePostfix = NULL)
{
if (thePrefix != NULL)
{
theStream << thePrefix;
}
theStream << std::setfill(' ') << std::setw (theWidth);
if (theValue >= 1024 * 1024 * 1024)
{
Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0 * 1024.0);
theStream << std::fixed << std::setprecision (1) << aValM << " GiB";
}
else if (theValue >= 1024 * 1024)
{
Standard_Real aValM = Standard_Real(theValue) / (1024.0 * 1024.0);
theStream << std::fixed << std::setprecision (1) << aValM << " MiB";
}
else if (theValue >= 1024)
{
Standard_Real aValK = Standard_Real(theValue) / 1024.0;
theStream << std::fixed << std::setprecision (1) << aValK << " KiB";
}
else
{
theStream << theValue << " B";
}
if (thePostfix != NULL)
{
theStream << thePostfix;
}
return theStream;
}
static const Standard_Real THE_SECONDS_IN_HOUR = 3600.0;
static const Standard_Real THE_SECONDS_IN_MINUTE = 60.0;
static const Standard_Real THE_SECOND_IN_HOUR = 1.0 / THE_SECONDS_IN_HOUR;
static const Standard_Real THE_SECOND_IN_MINUTE = 1.0 / THE_SECONDS_IN_MINUTE;
//! Format time.
static std::ostream& formatTime (std::ostream& theStream,
Standard_Integer theWidth,
const char* thePrefix,
Standard_Real theSeconds,
const char* thePostfix = NULL)
{
if (thePrefix != NULL)
{
theStream << thePrefix;
}
Standard_Real aSecIn = theSeconds;
unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
unsigned int aSeconds = (unsigned int )aSecIn;
aSecIn -= Standard_Real(aSeconds);
Standard_Real aMilliSeconds = 1000.0 * aSecIn;
char aBuffer[64];
theStream << std::setfill(' ') << std::setw (theWidth);
if (aHours > 0)
{
Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
theStream << aBuffer;
}
else if (aMinutes > 0)
{
Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
theStream << aBuffer;
}
else if (aSeconds > 0)
{
Sprintf (aBuffer, "%2u s", aSeconds);
theStream << aBuffer;
}
else
{
theStream << std::fixed << std::setprecision (1) << aMilliSeconds << " ms";
}
if (thePostfix != NULL)
{
theStream << thePostfix;
}
return theStream;
}
//! Add key-value pair to the dictionary.
static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
const TCollection_AsciiString& theKey,
const char* theValue)
{
TCollection_AsciiString aValue (theValue != NULL ? theValue : "");
theDict.ChangeFromIndex (theDict.Add (theKey, aValue)) = aValue;
}
//! Add key-value pair to the dictionary.
static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
const TCollection_AsciiString& theKey,
const Standard_Real theValue)
{
char aTmp[50];
Sprintf (aTmp, "%.1g", theValue);
addInfo (theDict, theKey, aTmp);
}
//! Add key-value pair to the dictionary.
static void addInfo (TColStd_IndexedDataMapOfStringString& theDict,
const TCollection_AsciiString& theKey,
const Standard_Size theValue)
{
char aTmp[50];
Sprintf (aTmp, "%zu", theValue);
addInfo (theDict, theKey, aTmp);
}
//! Format time.
static void addTimeInfo (TColStd_IndexedDataMapOfStringString& theDict,
const TCollection_AsciiString& theKey,
Standard_Real theSeconds)
{
Standard_Real aSecIn = theSeconds;
unsigned int aHours = (unsigned int )(aSecIn * THE_SECOND_IN_HOUR);
aSecIn -= Standard_Real(aHours) * THE_SECONDS_IN_HOUR;
unsigned int aMinutes = (unsigned int )(aSecIn * THE_SECOND_IN_MINUTE);
aSecIn -= Standard_Real(aMinutes) * THE_SECONDS_IN_MINUTE;
unsigned int aSeconds = (unsigned int )aSecIn;
aSecIn -= Standard_Real(aSeconds);
Standard_Real aMilliSeconds = 1000.0 * aSecIn;
char aBuffer[64];
if (aHours > 0)
{
Sprintf (aBuffer, "%02u:%02u:%02u", aHours, aMinutes, aSeconds);
}
else if (aMinutes > 0)
{
Sprintf (aBuffer, "%02u:%02u", aMinutes, aSeconds);
}
else if (aSeconds > 0)
{
Sprintf (aBuffer, "%2u", aSeconds);
}
else
{
addInfo (theDict, theKey, aMilliSeconds);
return;
}
addInfo (theDict, theKey, aBuffer);
}
}
// =======================================================================
// function : Graphic3d_FrameStats
// purpose :
// =======================================================================
Graphic3d_FrameStats::Graphic3d_FrameStats()
: myFpsTimer (Standard_True),
myFrameStartTime (0.0),
myFrameDuration (0.0),
myUpdateInterval (1.0),
myFpsFrameCount (0),
myCounters (0, 0),
myLastFrameIndex (0),
myIsLongLineFormat (Standard_False)
{
//
}
// =======================================================================
// function : ~Graphic3d_FrameStats
// purpose :
// =======================================================================
Graphic3d_FrameStats::~Graphic3d_FrameStats()
{
//
}
// =======================================================================
// function : FormatStats
// purpose :
// =======================================================================
TCollection_AsciiString Graphic3d_FrameStats::FormatStats (Graphic3d_RenderingParams::PerfCounters theFlags) const
{
const Standard_Integer aValWidth = 5;
std::stringstream aBuf;
const Standard_Boolean isCompact = theFlags == Graphic3d_RenderingParams::PerfCounters_FrameRate; // only FPS is displayed
const Graphic3d_FrameStatsData& aStats = LastDataFrame();
if (myIsLongLineFormat
&& (theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0
&& (theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
{
aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 9) << std::fixed << std::setprecision (1) << aStats.FrameRate()
<< " [CPU: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 10) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu() << "]\n";
}
else
{
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
{
aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRate();
if (aStats.ImmediateFrameRate() > 0.0)
{
aBuf << " (" << std::fixed << std::setprecision (1) << aStats.ImmediateFrameRate() << ")";
}
aBuf << "\n";
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
{
aBuf << "CPU FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << aStats.FrameRateCpu();
if (aStats.ImmediateFrameRateCpu() > 0.0)
{
aBuf << " (" << std::fixed << std::setprecision (1) << aStats.ImmediateFrameRateCpu() << ")";
}
aBuf << "\n";
}
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
{
if (myIsLongLineFormat)
{
formatCounter (aBuf, aValWidth, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
if (HasCulledLayers())
{
formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled], "]");
}
aBuf << "\n";
}
else
{
formatCounter (aBuf, aValWidth + 3, "Layers: ", aStats[Graphic3d_FrameStatsCounter_NbLayers], "\n");
}
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
{
if (myIsLongLineFormat)
{
formatCounter (aBuf, aValWidth, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
if (HasCulledStructs())
{
formatCounter (aBuf, aValWidth, " [rendered: ", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled], "]");
}
aBuf << "\n";
}
else
{
formatCounter (aBuf, aValWidth + 3, "Structs: ", aStats[Graphic3d_FrameStatsCounter_NbStructs], "\n");
}
}
const bool hasImmediate = aStats[Graphic3d_FrameStatsCounter_NbLayersImmediate] != 0 || aStats.ImmediateFrameRate() > 0.0;
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0
|| (theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0
|| (theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
|| (theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0
|| (theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0
|| (!myIsLongLineFormat
&& ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0
|| (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)))
{
if (hasImmediate)
{
aBuf << "Rendered (imm.)\n";
}
else
{
aBuf << "Rendered\n";
}
}
if (!myIsLongLineFormat
&& (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
{
formatCounterPair (aBuf, aValWidth, " Layers: ",
aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbLayersImmediate], hasImmediate);
}
if (!myIsLongLineFormat
&& (theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
{
formatCounterPair (aBuf, aValWidth, " Structs: ",
aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbStructsImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
{
formatCounterPair (aBuf, aValWidth, " Groups: ",
aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbGroupsImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
{
formatCounterPair (aBuf, aValWidth, " Arrays: ",
aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbElemsImmediate], hasImmediate);
formatCounterPair (aBuf, aValWidth, " [fill]: ",
aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbElemsFillImmediate], hasImmediate);
formatCounterPair (aBuf, aValWidth, " [line]: ",
aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbElemsLineImmediate], hasImmediate);
formatCounterPair (aBuf, aValWidth, " [point]: ",
aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbElemsPointImmediate], hasImmediate);
formatCounterPair (aBuf, aValWidth, " [text]: ",
aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbElemsTextImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
{
formatCounterPair (aBuf, aValWidth, " Triangles: ",
aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbTrianglesImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
{
formatCounterPair (aBuf, aValWidth, " Lines: ",
aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbLinesImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
{
formatCounterPair (aBuf, aValWidth, " Points: ",
aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled],
aStats[Graphic3d_FrameStatsCounter_NbPointsImmediate], hasImmediate);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
{
aBuf << "GPU Memory\n";
formatBytes (aBuf, aValWidth, " Geometry: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom], "\n");
formatBytes (aBuf, aValWidth, " Textures: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures], "\n");
formatBytes (aBuf, aValWidth, " Frames: ", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos], "\n");
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
{
aBuf << "Timers Average\n";
formatTime (aBuf, aValWidth, " Elapsed Frame: ", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame], "\n");
formatTime (aBuf, aValWidth, " CPU Frame: ", aStats[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
{
formatTime (aBuf, aValWidth, " CPU Picking: ", aStats[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
{
formatTime (aBuf, aValWidth, " CPU Culling: ", aStats[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
{
formatTime (aBuf, aValWidth, " CPU Dynamics: ", aStats[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
{
aBuf << "Timers Max\n";
formatTime (aBuf, aValWidth, " CPU Frame: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame], "\n");
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
{
formatTime (aBuf, aValWidth, " CPU Picking: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking], "\n");
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
{
formatTime (aBuf, aValWidth, " CPU Culling: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling], "\n");
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
{
formatTime (aBuf, aValWidth, " CPU Dynamics: ", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics], "\n");
}
}
}
return TCollection_AsciiString (aBuf.str().c_str());
}
// =======================================================================
// function : FormatStats
// purpose :
// =======================================================================
void Graphic3d_FrameStats::FormatStats (TColStd_IndexedDataMapOfStringString& theDict,
Graphic3d_RenderingParams::PerfCounters theFlags) const
{
const Graphic3d_FrameStatsData& aStats = LastDataFrame();
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
{
addInfo (theDict, "FPS", aStats.FrameRate());
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
{
addInfo (theDict, "CPU FPS", aStats.FrameRateCpu());
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
{
addInfo (theDict, "Layers", aStats[Graphic3d_FrameStatsCounter_NbLayers]);
if (HasCulledLayers())
{
addInfo (theDict, "Rendered layers", aStats[Graphic3d_FrameStatsCounter_NbLayersNotCulled]);
}
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
{
addInfo (theDict, "Structs", aStats[Graphic3d_FrameStatsCounter_NbStructs]);
if (HasCulledStructs())
{
addInfo (theDict, "Rendered structs", aStats[Graphic3d_FrameStatsCounter_NbStructsNotCulled]);
}
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
{
addInfo (theDict, "Rendered groups", aStats[Graphic3d_FrameStatsCounter_NbGroupsNotCulled]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
{
addInfo (theDict, "Rendered arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsNotCulled]);
addInfo (theDict, "Rendered [fill] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled]);
addInfo (theDict, "Rendered [line] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled]);
addInfo (theDict, "Rendered [point] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled]);
addInfo (theDict, "Rendered [text] arrays", aStats[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
{
addInfo (theDict, "Rendered triangles", aStats[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Lines) != 0)
{
addInfo (theDict, "Rendered lines", aStats[Graphic3d_FrameStatsCounter_NbLinesNotCulled]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
{
addInfo (theDict, "Rendered points", aStats[Graphic3d_FrameStatsCounter_NbPointsNotCulled]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
{
addInfo (theDict, "GPU Memory [geometry]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesGeom]);
addInfo (theDict, "GPU Memory [textures]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesTextures]);
addInfo (theDict, "GPU Memory [frames]", aStats[Graphic3d_FrameStatsCounter_EstimatedBytesFbos]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
{
addTimeInfo (theDict, "Elapsed Frame (average)", aStats[Graphic3d_FrameStatsTimer_ElapsedFrame]);
addTimeInfo (theDict, "CPU Frame (average)", aStats[Graphic3d_FrameStatsTimer_CpuFrame]);
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
{
addTimeInfo (theDict, "CPU Picking (average)", aStats[Graphic3d_FrameStatsTimer_CpuPicking]);
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
{
addTimeInfo (theDict, "CPU Culling (average)", aStats[Graphic3d_FrameStatsTimer_CpuCulling]);
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
{
addTimeInfo (theDict, "CPU Dynamics (average)", aStats[Graphic3d_FrameStatsTimer_CpuDynamics]);
}
if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameTimeMax) != 0)
{
addTimeInfo (theDict, "CPU Frame (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuFrame]);
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking] > 0.0)
{
addTimeInfo (theDict, "CPU Picking (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuPicking]);
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling] > 0.0)
{
addTimeInfo (theDict, "CPU Culling (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuCulling]);
}
if (myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics])
{
addTimeInfo (theDict, "CPU Dynamics (max)", myCountersMax[Graphic3d_FrameStatsTimer_CpuDynamics]);
}
}
}
}
// =======================================================================
// function : FrameStart
// purpose :
// =======================================================================
void Graphic3d_FrameStats::FrameStart (const Handle(Graphic3d_CView)& theView,
bool theIsImmediateOnly)
{
const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
? theView->RenderingParams().CollectedStats
: Graphic3d_RenderingParams::PerfCounters_NONE;
if (theIsImmediateOnly
&& (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
{
return;
}
const Standard_Integer aNbFrames = Max (!theView.IsNull()
? theView->RenderingParams().StatsNbFrames
: 1, 1);
if (myCounters.Size() != aNbFrames)
{
myCounters.Resize (0, aNbFrames - 1, false);
myCounters.Init (Graphic3d_FrameStatsData());
myLastFrameIndex = myCounters.Upper();
}
// reset values at the end of frame (after data has been flushed),
// so that application can put some counters (like picking time) before FrameStart().
//myCountersTmp.Reset();
myFrameStartTime = myFpsTimer.ElapsedTime();
if (!myFpsTimer.IsStarted())
{
myFpsTimer.Reset();
myFpsTimer.Start();
myFpsFrameCount = 0;
}
}
// =======================================================================
// function : FrameEnd
// purpose :
// =======================================================================
void Graphic3d_FrameStats::FrameEnd (const Handle(Graphic3d_CView)& theView,
bool theIsImmediateOnly)
{
const Graphic3d_RenderingParams::PerfCounters aBits = !theView.IsNull()
? theView->RenderingParams().CollectedStats
: Graphic3d_RenderingParams::PerfCounters_NONE;
if (theIsImmediateOnly
&& (aBits & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
{
return;
}
const double aTime = myFpsTimer.ElapsedTime();
myFrameDuration = aTime - myFrameStartTime;
++myFpsFrameCount;
if (!theView.IsNull())
{
myUpdateInterval = theView->RenderingParams().StatsUpdateInterval;
}
if (aTime < myUpdateInterval)
{
myCountersTmp.FlushTimers (myFpsFrameCount, false);
return;
}
const Graphic3d_FrameStatsData& aPrevFrame = myCounters.Value (myLastFrameIndex);
if (aTime > gp::Resolution())
{
// update FPS
myFpsTimer.Stop();
const double aCpuSec = myFpsTimer.UserTimeCPU();
myCountersTmp[Graphic3d_FrameStatsTimer_ElapsedFrame] = aTime;
myCountersTmp[Graphic3d_FrameStatsTimer_CpuFrame] = aCpuSec;
if (theIsImmediateOnly)
{
myCountersTmp.ChangeImmediateFrameRate() = double(myFpsFrameCount) / aTime;
myCountersTmp.ChangeImmediateFrameRateCpu() = aCpuSec > gp::Resolution()
? double(myFpsFrameCount) / aCpuSec
: -1.0;
myCountersTmp.ChangeFrameRate() = aPrevFrame.FrameRate();
myCountersTmp.ChangeFrameRateCpu() = aPrevFrame.FrameRateCpu();
}
else
{
myCountersTmp.ChangeImmediateFrameRate() = -1.0;
myCountersTmp.ChangeImmediateFrameRateCpu() = -1.0;
myCountersTmp.ChangeFrameRate() = double(myFpsFrameCount) / aTime;
myCountersTmp.ChangeFrameRateCpu() = aCpuSec > gp::Resolution()
? double(myFpsFrameCount) / aCpuSec
: -1.0;
}
myCountersTmp.FlushTimers (myFpsFrameCount, true);
myCountersMax.FillMax (myCountersTmp);
myFpsTimer.Reset();
myFpsTimer.Start();
myFpsFrameCount = 0;
}
// update structure counters
if (theView.IsNull())
{
myCounters.SetValue (myLastFrameIndex, myCountersTmp);
myCountersTmp.Reset();
return;
}
updateStatistics (theView, theIsImmediateOnly);
if (++myLastFrameIndex > myCounters.Upper())
{
myLastFrameIndex = myCounters.Lower();
}
if (theIsImmediateOnly)
{
// copy rendered counters collected for immediate layers
const Standard_Integer anImmShift = Graphic3d_FrameStatsCounter_IMMEDIATE_LOWER - Graphic3d_FrameStatsCounter_RENDERED_LOWER;
Standard_STATIC_ASSERT((Graphic3d_FrameStatsCounter_RENDERED_UPPER - Graphic3d_FrameStatsCounter_RENDERED_LOWER) == (Graphic3d_FrameStatsCounter_IMMEDIATE_UPPER - Graphic3d_FrameStatsCounter_IMMEDIATE_LOWER))
for (Standard_Integer aCntIter = Graphic3d_FrameStatsCounter_RENDERED_LOWER; aCntIter <= Graphic3d_FrameStatsCounter_RENDERED_UPPER; ++aCntIter)
{
myCountersTmp.ChangeCounterValue ((Graphic3d_FrameStatsCounter )(aCntIter + anImmShift)) = myCountersTmp.CounterValue ((Graphic3d_FrameStatsCounter )aCntIter);
}
// copy main rendered counters from previous non-immediate frame
for (Standard_Integer aCntIter = Graphic3d_FrameStatsCounter_RENDERED_LOWER; aCntIter <= Graphic3d_FrameStatsCounter_RENDERED_UPPER; ++aCntIter)
{
myCountersTmp.ChangeCounterValue ((Graphic3d_FrameStatsCounter )aCntIter) = aPrevFrame.CounterValue ((Graphic3d_FrameStatsCounter )aCntIter);
}
myCountersTmp.ChangeCounterValue (Graphic3d_FrameStatsCounter_EstimatedBytesGeom) = aPrevFrame.CounterValue (Graphic3d_FrameStatsCounter_EstimatedBytesGeom);
}
myCounters.SetValue (myLastFrameIndex, myCountersTmp);
myCountersTmp.Reset();
}