Graphic3d_RenderingParams::ToShowStats - new option displaying rendering statistics.
OpenGl_FrameStats - new class for accumulating frame statistics.
OpenGl_Context::FrameStats() provides an access to the frame stats
used for currently rendered context.
OpenGl_View::Redraw() and OpenGl_View::RedrawImmediate()
resets counters within OpenGl_Context::FrameStats().
OpenGl_Layer::UpdateCulling() - simplified resetting of culling state for cullable structures.
vinit View1 w=1024 h=1024
vclear
+vdefaults -autoTriang 0
+vrenderparams -stats basic
# parameter NB defines number of spheres by each coordinate
set NB 10
}
}
}
+eval compound $slist c
+incmesh c 0.006
puts "Measuring FPS of display of spheres as separate objects..."
vaxo
-vsetdispmode 1
-eval vdisplay $slist
+eval vdisplay -dispMode 1 $slist
vfit
# measure FPS
vclear
puts "Measuring FPS of display of spheres as single object..."
-eval compound $slist c
-vdisplay c
+vdisplay -dispMode 1 c
# measure FPS
puts [set fps_compound [vfps]]
vclear
# redisplay individual spheres, trying to avoid unnecessary internal updates
-#vfrustumculling 0 ;# try to disable updates of frustum culling structures
-eval vdisplay -mutable $slist
+eval vdisplay -dispMode 1 $slist
# auxiliary procedure to make random update of variable
proc upd {theValueName theDeltaName theTime theToRand} {
for {set i 0} {$i < $::NB} {incr i $nb} {
for {set j 0} {$j < $::NB} {incr j $nb} {
for {set k 0} {$k < $::NB} {incr k $nb} {
+ # mark animated spheres mutable for faster updates
+ uplevel #0 vdisplay -dispMode 1 -mutable s$i$j$k
# vaspects -noupdate s$i$j$k -setcolor red -setmaterial plastic
- vaspects -noupdate s$i$j$k -setcolor red
+ uplevel #0 vaspects -noupdate s$i$j$k -setcolor red
set x$i$j$k 0.0
set y$i$j$k 0.0
set z$i$j$k 0.0
puts ""
puts "Scene contains [lindex [trinfo c] 3] triangles"
puts ""
-puts "Print 'animateSpheres 10.0' to restart animation"
\ No newline at end of file
+puts "Print 'animateSpheres 10.0' to restart animation"
#ifndef _Graphic3d_RenderingParams_HeaderFile
#define _Graphic3d_RenderingParams_HeaderFile
-#include <Graphic3d_Mat4.hxx>
+#include <Graphic3d_AspectText3d.hxx>
+#include <Graphic3d_TransformPers.hxx>
#include <Graphic3d_RenderTransparentMethod.hxx>
#include <Graphic3d_RenderingMode.hxx>
#include <Graphic3d_StereoMode.hxx>
Anaglyph_UserDefined //!< use externally specified matrices
};
+ //! Statistics display flags.
+ enum PerfCounters
+ {
+ PerfCounters_NONE = 0x000, //!< no stats
+ PerfCounters_FrameRate = 0x001, //!< Frame Rate
+ PerfCounters_CPU = 0x002, //!< CPU utilization
+ PerfCounters_Layers = 0x004, //!< count layers (groups of structures)
+ PerfCounters_Structures = 0x008, //!< count low-level Structures (normal unhighlighted Presentable Object is usually represented by 1 Structure)
+ //
+ PerfCounters_Groups = 0x010, //!< count primitive Groups (1 Structure holds 1 or more primitive Group)
+ PerfCounters_GroupArrays = 0x020, //!< count Arrays within Primitive Groups (optimal primitive Group holds 1 Array)
+ //
+ PerfCounters_Triangles = 0x040, //!< count Triangles
+ PerfCounters_Points = 0x080, //!< count Points
+ //
+ PerfCounters_EstimMem = 0x100, //!< estimated GPU memory usage
+ //! show basic statistics
+ PerfCounters_Basic = PerfCounters_FrameRate | PerfCounters_CPU | PerfCounters_Layers | PerfCounters_Structures,
+ //! extended (verbose) statistics
+ PerfCounters_Extended = PerfCounters_Basic
+ | PerfCounters_Groups | PerfCounters_GroupArrays
+ | PerfCounters_Triangles | PerfCounters_Points
+ | PerfCounters_EstimMem,
+ };
+
public:
//! Creates default rendering parameters.
StereoMode (Graphic3d_StereoMode_QuadBuffer),
AnaglyphFilter (Anaglyph_RedCyan_Optimized),
ToReverseStereo (Standard_False),
-
+ //
+ StatsPosition (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i (20, 20))),
+ StatsTextAspect (new Graphic3d_AspectText3d()),
+ StatsUpdateInterval (1.0),
+ StatsTextHeight (16),
+ CollectedStats (PerfCounters_Basic),
+ ToShowStats (Standard_False),
+ //
Resolution (THE_DEFAULT_RESOLUTION)
{
const Graphic3d_Vec4 aZero (0.0f, 0.0f, 0.0f, 0.0f);
AnaglyphRight.SetRow (1, Graphic3d_Vec4 (0.0f, 1.0f, 0.0f, 0.0f));
AnaglyphRight.SetRow (2, Graphic3d_Vec4 (0.0f, 0.0f, 1.0f, 0.0f));
AnaglyphRight.SetRow (3, aZero);
+
+ StatsTextAspect->SetColor (Quantity_NOC_WHITE);
+ StatsTextAspect->SetColorSubTitle (Quantity_NOC_BLACK);
+ StatsTextAspect->SetFont (Font_NOF_ASCII_MONO);
+ StatsTextAspect->SetDisplayType (Aspect_TODT_SHADOW);
+ StatsTextAspect->SetTextZoomable (Standard_False);
+ StatsTextAspect->SetTextFontAspect (Font_FA_Regular);
}
//! Returns resolution ratio.
Graphic3d_Mat4 AnaglyphRight; //!< right anaglyph filter (in normalized colorspace), Color = AnaglyphRight * theColorRight + AnaglyphLeft * theColorLeft;
Standard_Boolean ToReverseStereo; //!< flag to reverse stereo pair, FALSE by default
+ Handle(Graphic3d_TransformPers) StatsPosition; //!< location of stats, upper-left position by default
+ Handle(Graphic3d_AspectText3d) StatsTextAspect; //!< stats text aspect
+ Standard_ShortReal StatsUpdateInterval; //!< time interval between stats updates in seconds, 1.0 second by default;
+ //! too often updates might impact performance and will smear text within widgets
+ //! (especially framerate, which is better averaging);
+ //! 0.0 interval will force updating on each frame
+ Standard_Integer StatsTextHeight; //!< stats text size; 16 by default
+ PerfCounters CollectedStats; //!< performance counters to collect, PerfCounters_Basic by default;
+ //! too verbose options might impact rendering performance,
+ //! because some counters might lack caching optimization (and will require expensive iteration through all data structures)
+ Standard_Boolean ToShowStats; //!< display performance statistics, FALSE by default;
+ //! note that counters specified within CollectedStats will be updated nevertheless
+ //! of visibility of widget managed by ToShowStats flag (e.g. stats can be retrieved by application for displaying using other methods)
+
unsigned int Resolution; //!< Pixels density (PPI), defines scaling factor for parameters like text size
//! (when defined in screen-space units rather than in 3D) to be properly displayed
//! on device (screen / printer). 72 is default value.
OpenGl_AspectMarker.hxx
OpenGl_AspectText.cxx
OpenGl_AspectText.hxx
+OpenGl_FrameStats.cxx
+OpenGl_FrameStats.hxx
+OpenGl_FrameStatsPrs.cxx
+OpenGl_FrameStatsPrs.hxx
OpenGl_Group.hxx
OpenGl_Group.cxx
OpenGl_Structure.hxx
//! Returns the structure corresponding to the given ID.
const OpenGl_Structure* GetStructureById (Standard_Integer theId);
+ //! Access directly a collection of structures.
+ const NCollection_IndexedMap<const OpenGl_Structure*>& Structures() const { return myStructs; }
+
private:
NCollection_IndexedMap<const OpenGl_Structure*> myStructs; //!< Indexed map of structures.
//! Returns the structure corresponding to the given ID.
const OpenGl_Structure* GetStructureById (Standard_Integer theId);
+ //! Access directly a collection of structures.
+ const NCollection_IndexedMap<const OpenGl_Structure*>& Structures() const { return myStructs; }
+
//! Marks object state as outdated (needs BVH rebuilding).
void MarkDirty()
{
//! @param theContext [in] the resource context.
Standard_EXPORT virtual void Release (OpenGl_Context* theContext) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage - not implemented.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE { return 0; }
+
//! Return parent clipping plane structure.
const Handle(Graphic3d_ClipPlane)& Plane() const { return myPlaneRoot; }
#include <OpenGl_ArbTexBindless.hxx>
#include <OpenGl_GlCore44.hxx>
#include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_FrameStats.hxx>
#include <OpenGl_Sampler.hxx>
#include <OpenGl_ShaderManager.hxx>
#include <OpenGl_Workspace.hxx>
myHasRayTracing (Standard_False),
myHasRayTracingTextures (Standard_False),
myHasRayTracingAdaptiveSampling (Standard_False),
+ myFrameStats (new OpenGl_FrameStats()),
#if !defined(GL_ES_VERSION_2_0)
myPointSpriteOrig (GL_UPPER_LEFT),
myRenderMode (GL_RENDER),
class OpenGl_Sampler;
class OpenGl_ShaderProgram;
class OpenGl_ShaderManager;
+class OpenGl_FrameStats;
enum OpenGl_FeatureFlag
{
friend class OpenGl_Window;
public:
+ typedef NCollection_Shared< NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)> > OpenGl_ResourcesMap;
+
//! Function for getting power of to number larger or equal to input number.
//! @param theNumber number to 'power of two'
//! @param theThreshold upper threshold
//! Clean up the delayed release queue.
Standard_EXPORT void ReleaseDelayed();
+ //! Return map of shared resources.
+ const OpenGl_ResourcesMap& SharedResources() const { return *mySharedResources; }
+
//! @return tool for management of clippings within this context.
inline OpenGl_Clipping& ChangeClipping() { return myClippingState; }
public: //! @name methods to alter or retrieve current state
+ //! Return structure holding frame statistics.
+ const Handle(OpenGl_FrameStats)& FrameStats() const { return myFrameStats; }
+
//! Return cached viewport definition (x, y, width, height).
const Standard_Integer* Viewport() const { return myViewport; }
private: // context info
typedef NCollection_Shared< NCollection_DataMap<TCollection_AsciiString, Standard_Integer> > OpenGl_DelayReleaseMap;
- typedef NCollection_Shared< NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)> > OpenGl_ResourcesMap;
typedef NCollection_Shared< NCollection_List<Handle(OpenGl_Resource)> > OpenGl_ResourcesStack;
typedef NCollection_SparseArray<Standard_Integer> OpenGl_DrawBuffers;
private: //! @name fields tracking current state
+ Handle(OpenGl_FrameStats) myFrameStats; //!< structure accumulating frame statistics
Handle(OpenGl_ShaderProgram) myActiveProgram; //!< currently active GLSL program
Handle(OpenGl_TextureSet) myActiveTextures; //!< currently bound textures
//!< currently active sampler objects
myTextures.Clear();
}
+// =======================================================================
+// function : EstimatedDataSize
+// purpose :
+// =======================================================================
+Standard_Size OpenGl_Font::EstimatedDataSize() const
+{
+ Standard_Size aSize = 0;
+ for (NCollection_Vector<Handle(OpenGl_Texture)>::Iterator aTexIter (myTextures); aTexIter.More(); aTexIter.Next())
+ {
+ aSize += aTexIter.Value()->EstimatedDataSize();
+ }
+ return aSize;
+}
+
// =======================================================================
// function : Init
// purpose :
//! Destroy object - will release GPU memory if any
Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage.
+ Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
+
//! @return key of shared resource
inline const TCollection_AsciiString& ResourceKey() const
{
return !hasErrors;
}
+
+// =======================================================================
+// function : EstimatedDataSize
+// purpose :
+// =======================================================================
+Standard_Size OpenGl_FrameBuffer::EstimatedDataSize() const
+{
+ if (!IsValid())
+ {
+ return 0;
+ }
+
+ Standard_Size aSize = 0;
+ for (OpenGl_TextureArray::Iterator aTextureIt (myColorTextures); aTextureIt.More(); aTextureIt.Next())
+ {
+ aSize += aTextureIt.Value()->EstimatedDataSize();
+ }
+ if (!myDepthStencilTexture.IsNull())
+ {
+ aSize += myDepthStencilTexture->EstimatedDataSize();
+ }
+ if (myGlColorRBufferId != NO_RENDERBUFFER
+ && !myColorFormats.IsEmpty())
+ {
+ aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myColorFormats.First()) * myInitVPSizeX * myInitVPSizeY;
+ }
+ if (myGlDepthRBufferId != NO_RENDERBUFFER)
+ {
+ aSize += OpenGl_Texture::PixelSizeOfPixelFormat (myDepthFormat) * myInitVPSizeX * myInitVPSizeY;
+ }
+ return aSize;
+}
return myGlDepthRBufferId;
}
+ //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
+ Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
+
protected:
Standard_Boolean isValidFrameBuffer() const
--- /dev/null
+// 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 <OpenGl_FrameStats.hxx>
+
+#include <OpenGl_GlCore20.hxx>
+#include <OpenGl_View.hxx>
+#include <OpenGl_Workspace.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_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 << thePostfix;
+ }
+ 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;
+ }
+ if (thePostfix != NULL)
+ {
+ theStream << thePostfix;
+ }
+ return theStream;
+ }
+
+ //! Return estimated data size.
+ static Standard_Size estimatedDataSize (const Handle(OpenGl_Resource)& theRes)
+ {
+ return !theRes.IsNull() ? theRes->EstimatedDataSize() : 0;
+ }
+}
+
+// =======================================================================
+// function : OpenGl_FrameStats
+// purpose :
+// =======================================================================
+OpenGl_FrameStats::OpenGl_FrameStats()
+: myFpsTimer (Standard_True),
+ myFrameStartTime (0.0),
+ myFrameDuration (0.0),
+ myFps (-1.0),
+ myFpsCpu (-1.0),
+ myUpdateInterval (1.0),
+ myFpsFrameCount (0),
+ myIsLongLineFormat (Standard_False)
+{
+ memset (myCounters, 0, sizeof(myCounters));
+ memset (myCountersTmp, 0, sizeof(myCountersTmp));
+}
+
+// =======================================================================
+// function : ~OpenGl_FrameStats
+// purpose :
+// =======================================================================
+OpenGl_FrameStats::~OpenGl_FrameStats()
+{
+ //
+}
+
+// =======================================================================
+// function : FormatStats
+// purpose :
+// =======================================================================
+TCollection_AsciiString OpenGl_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
+ 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) << myFps
+ << " [CPU: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : 10) << std::fixed << std::setprecision (1) << myFpsCpu << "]\n";
+ }
+ else
+ {
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
+ {
+ aBuf << "FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << myFps << "\n";
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
+ {
+ aBuf << "CPU FPS: " << std::setfill(' ') << std::setw (isCompact ? aValWidth : aValWidth + 3) << std::fixed << std::setprecision (1) << myFpsCpu << "\n";
+ }
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
+ {
+ if (myIsLongLineFormat)
+ {
+ formatCounter (aBuf, aValWidth, "Layers: ", myCounters[Counter_NbLayers]);
+ if (HasCulledLayers())
+ {
+ formatCounter (aBuf, aValWidth, " [rendered: ", myCounters[Counter_NbLayersNotCulled], "]");
+ }
+ aBuf << "\n";
+ }
+ else
+ {
+ formatCounter (aBuf, aValWidth + 3, "Layers: ", myCounters[Counter_NbLayers], "\n");
+ }
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
+ {
+ if (myIsLongLineFormat)
+ {
+ formatCounter (aBuf, aValWidth, "Structs: ", myCounters[Counter_NbStructs]);
+ if (HasCulledStructs())
+ {
+ formatCounter (aBuf, aValWidth, " [rendered: ", myCounters[Counter_NbStructsNotCulled], "]");
+ }
+ aBuf << "\n";
+ }
+ else
+ {
+ formatCounter (aBuf, aValWidth + 3, "Structs: ", myCounters[Counter_NbStructs], "\n");
+ }
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0
+ || (theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0
+ || (theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
+ || (theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0
+ || (!myIsLongLineFormat
+ && ((theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0
+ || (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)))
+ {
+ aBuf << "Rendered\n";
+ }
+ if (!myIsLongLineFormat
+ && (theFlags & Graphic3d_RenderingParams::PerfCounters_Layers) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Layers: ", myCounters[Counter_NbLayersNotCulled], "\n");
+ }
+ if (!myIsLongLineFormat
+ && (theFlags & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Structs: ", myCounters[Counter_NbStructsNotCulled], "\n");
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Groups: ", myCounters[Counter_NbGroupsNotCulled], "\n");
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Arrays: ", myCounters[Counter_NbElemsNotCulled], "\n");
+ formatCounter (aBuf, aValWidth, " [fill]: ", myCounters[Counter_NbElemsFillNotCulled], "\n");
+ formatCounter (aBuf, aValWidth, " [line]: ", myCounters[Counter_NbElemsLineNotCulled], "\n");
+ formatCounter (aBuf, aValWidth, " [point]: ", myCounters[Counter_NbElemsPointNotCulled], "\n");
+ formatCounter (aBuf, aValWidth, " [text]: ", myCounters[Counter_NbElemsTextNotCulled], "\n");
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Triangles: ", myCounters[Counter_NbTrianglesNotCulled], "\n");
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
+ {
+ formatCounter (aBuf, aValWidth, " Points: ", myCounters[Counter_NbPointsNotCulled], "\n");
+ }
+ if ((theFlags & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
+ {
+ aBuf << "GPU Memory\n";
+ formatBytes (aBuf, aValWidth, " Geometry: ", myCounters[Counter_EstimatedBytesGeom], "\n");
+ formatBytes (aBuf, aValWidth, " Textures: ", myCounters[Counter_EstimatedBytesTextures], "\n");
+ formatBytes (aBuf, aValWidth, " Frames: ", myCounters[Counter_EstimatedBytesFbos], "\n");
+ }
+ return TCollection_AsciiString (aBuf.str().c_str());
+}
+
+// =======================================================================
+// function : FrameStart
+// purpose :
+// =======================================================================
+void OpenGl_FrameStats::FrameStart (const Handle(OpenGl_Workspace)& )
+{
+ memset (myCountersTmp, 0, sizeof(myCountersTmp));
+ myFrameStartTime = myFpsTimer.ElapsedTime();
+ if (!myFpsTimer.IsStarted())
+ {
+ myFpsTimer.Reset();
+ myFpsTimer.Start();
+ myFpsFrameCount = 0;
+ }
+}
+
+// =======================================================================
+// function : FrameEnd
+// purpose :
+// =======================================================================
+void OpenGl_FrameStats::FrameEnd (const Handle(OpenGl_Workspace)& theWorkspace)
+{
+ const Graphic3d_RenderingParams::PerfCounters aBits = !theWorkspace.IsNull()
+ ? theWorkspace->View()->RenderingParams().CollectedStats
+ : Graphic3d_RenderingParams::PerfCounters_NONE;
+ const double aTime = myFpsTimer.ElapsedTime();
+ myFrameDuration = aTime - myFrameStartTime;
+ ++myFpsFrameCount;
+ if (!theWorkspace.IsNull())
+ {
+ myUpdateInterval = theWorkspace->View()->RenderingParams().StatsUpdateInterval;
+ }
+
+ if (aTime < myUpdateInterval)
+ {
+ return;
+ }
+
+ if (aTime > gp::Resolution())
+ {
+ // update FPS
+ myFpsTimer.Stop();
+ const double aCpuSec = myFpsTimer.UserTimeCPU();
+ myFps = double(myFpsFrameCount) / aTime;
+ myFpsCpu = aCpuSec > gp::Resolution()
+ ? double(myFpsFrameCount) / aCpuSec
+ : -1.0;
+ myFpsTimer.Reset();
+ myFpsTimer.Start();
+ myFpsFrameCount = 0;
+ }
+
+ // update structure counters
+ if (theWorkspace.IsNull())
+ {
+ memcpy (myCounters, myCountersTmp, sizeof(myCounters));
+ return;
+ }
+
+ const Standard_Boolean toCountMem = (aBits & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0;
+ const Standard_Boolean toCountTris = (aBits & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
+ || (aBits & Graphic3d_RenderingParams::PerfCounters_Points) != 0;
+ const Standard_Boolean toCountElems = (aBits & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0 || toCountTris || toCountMem;
+ const Standard_Boolean toCountGroups = (aBits & Graphic3d_RenderingParams::PerfCounters_Groups) != 0 || toCountElems;
+ const Standard_Boolean toCountStructs = (aBits & Graphic3d_RenderingParams::PerfCounters_Structures) != 0 || toCountGroups;
+
+ if (toCountStructs)
+ {
+ myCountersTmp[Counter_NbLayers] = theWorkspace->View()->LayerList().Layers().Size();
+ for (OpenGl_SequenceOfLayers::Iterator aLayerIter (theWorkspace->View()->LayerList().Layers()); aLayerIter.More(); aLayerIter.Next())
+ {
+ const Handle(OpenGl_Layer)& aLayer = aLayerIter.Value();
+ if (!aLayer->IsCulled())
+ {
+ ++myCountersTmp[Counter_NbLayersNotCulled];
+ }
+ myCountersTmp[Counter_NbStructs] += aLayer->NbStructures();
+ myCountersTmp[Counter_NbStructsNotCulled] += aLayer->NbStructuresNotCulled();
+ if (toCountGroups)
+ {
+ updateStructures (aLayer->CullableStructuresBVH().Structures(), toCountStructs, toCountTris, toCountMem);
+ updateStructures (aLayer->CullableTrsfPersStructuresBVH().Structures(), toCountStructs, toCountTris, toCountMem);
+ updateStructures (aLayer->NonCullableStructures(), toCountStructs, toCountTris, toCountMem);
+ }
+ }
+ }
+ if (toCountMem
+ && !theWorkspace.IsNull())
+ {
+ for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (theWorkspace->GetGlContext()->SharedResources());
+ aResIter.More(); aResIter.Next())
+ {
+ myCountersTmp[Counter_EstimatedBytesTextures] += aResIter.Value()->EstimatedDataSize();
+ }
+
+ const OpenGl_View* aView = theWorkspace->View();
+ {
+ Standard_Size& aMemFbos = myCountersTmp[Counter_EstimatedBytesFbos];
+ // main FBOs
+ aMemFbos += estimatedDataSize (aView->myMainSceneFbos[0]);
+ aMemFbos += estimatedDataSize (aView->myMainSceneFbos[1]);
+ aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[0]);
+ aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[1]);
+ // OIT FBOs
+ aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[0]);
+ aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]);
+ aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]);
+ aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]);
+ // dump FBO
+ aMemFbos += estimatedDataSize (aView->myFBO);
+ // RayTracing FBO
+ aMemFbos += estimatedDataSize (aView->myOpenGlFBO);
+ aMemFbos += estimatedDataSize (aView->myOpenGlFBO2);
+ aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[0]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[1]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[0]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[1]);
+ // also RayTracing
+ aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[0]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[1]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[0]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[1]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[0]);
+ aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[1]);
+ }
+ {
+ // Ray Tracing geometry
+ Standard_Size& aMemGeom = myCountersTmp[Counter_EstimatedBytesGeom];
+ aMemGeom += estimatedDataSize (aView->mySceneNodeInfoTexture);
+ aMemGeom += estimatedDataSize (aView->mySceneMinPointTexture);
+ aMemGeom += estimatedDataSize (aView->mySceneMaxPointTexture);
+ aMemGeom += estimatedDataSize (aView->mySceneTransformTexture);
+ aMemGeom += estimatedDataSize (aView->myGeometryVertexTexture);
+ aMemGeom += estimatedDataSize (aView->myGeometryNormalTexture);
+ aMemGeom += estimatedDataSize (aView->myGeometryTexCrdTexture);
+ aMemGeom += estimatedDataSize (aView->myGeometryTriangTexture);
+ aMemGeom += estimatedDataSize (aView->myRaytraceMaterialTexture);
+ aMemGeom += estimatedDataSize (aView->myRaytraceLightSrcTexture);
+ }
+ }
+ memcpy (myCounters, myCountersTmp, sizeof(myCounters));
+}
+
+// =======================================================================
+// function : updateStructures
+// purpose :
+// =======================================================================
+void OpenGl_FrameStats::updateStructures (const OpenGl_IndexedMapOfStructure& theStructures,
+ Standard_Boolean theToCountElems,
+ Standard_Boolean theToCountTris,
+ Standard_Boolean theToCountMem)
+{
+ for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (theStructures); aStructIter.More(); aStructIter.Next())
+ {
+ const OpenGl_Structure* aStruct = aStructIter.Value();
+ if (aStruct->IsCulled())
+ {
+ if (theToCountMem)
+ {
+ for (OpenGl_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ const OpenGl_Group* aGroup = aGroupIter.Value();
+ for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next)
+ {
+ if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast<const OpenGl_PrimitiveArray*> (aNodeIter->elem))
+ {
+ myCountersTmp[Counter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo());
+ myCountersTmp[Counter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo());
+ }
+ }
+ }
+ }
+ continue;
+ }
+
+ myCountersTmp[Counter_NbGroupsNotCulled] += aStruct->Groups().Size();
+ if (!theToCountElems)
+ {
+ continue;
+ }
+
+ for (OpenGl_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next())
+ {
+ const OpenGl_Group* aGroup = aGroupIter.Value();
+ for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next)
+ {
+ if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast<const OpenGl_PrimitiveArray*> (aNodeIter->elem))
+ {
+ ++myCountersTmp[Counter_NbElemsNotCulled];
+ if (theToCountMem)
+ {
+ myCountersTmp[Counter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo());
+ myCountersTmp[Counter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo());
+ }
+
+ if (aPrim->IsFillDrawMode())
+ {
+ ++myCountersTmp[Counter_NbElemsFillNotCulled];
+ if (!theToCountTris)
+ {
+ continue;
+ }
+
+ const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo();
+ if (anAttribs.IsNull()
+ || !anAttribs->IsValid())
+ {
+ continue;
+ }
+
+ const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo();
+ const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb();
+ const Standard_Integer aNbBounds = !aPrim->Bounds().IsNull() ? aPrim->Bounds()->NbBounds : 1;
+ switch (aPrim->DrawMode())
+ {
+ case GL_TRIANGLES:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += aNbIndices / 3;
+ break;
+ }
+ case GL_TRIANGLE_STRIP:
+ case GL_TRIANGLE_FAN:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds;
+ break;
+ }
+ case GL_TRIANGLES_ADJACENCY:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += aNbIndices / 6;
+ break;
+ }
+ case GL_TRIANGLE_STRIP_ADJACENCY:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds;
+ break;
+ }
+ #if !defined(GL_ES_VERSION_2_0)
+ case GL_QUADS:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += aNbIndices / 2;
+ break;
+ }
+ case GL_QUAD_STRIP:
+ {
+ myCountersTmp[Counter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2;
+ break;
+ }
+ #endif
+ }
+ }
+ else if (aPrim->DrawMode() == GL_POINTS)
+ {
+ ++myCountersTmp[Counter_NbElemsPointNotCulled];
+ if (theToCountTris)
+ {
+ const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo();
+ if (!anAttribs.IsNull()
+ && anAttribs->IsValid())
+ {
+ const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo();
+ const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb();
+ myCountersTmp[Counter_NbPointsNotCulled] += aNbIndices;
+ }
+ }
+ }
+ else
+ {
+ ++myCountersTmp[Counter_NbElemsLineNotCulled];
+ }
+ }
+ else if (const OpenGl_Text* aText = dynamic_cast<const OpenGl_Text*> (aNodeIter->elem))
+ {
+ (void )aText;
+ ++myCountersTmp[Counter_NbElemsNotCulled];
+ ++myCountersTmp[Counter_NbElemsTextNotCulled];
+ }
+ }
+ }
+ }
+}
--- /dev/null
+// 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.
+
+#ifndef _OpenGl_FrameStats_HeaderFile
+#define _OpenGl_FrameStats_HeaderFile
+
+#include <Graphic3d_RenderingParams.hxx>
+#include <NCollection_IndexedMap.hxx>
+#include <OSD_Timer.hxx>
+#include <Standard_Type.hxx>
+#include <Standard_Transient.hxx>
+
+class OpenGl_Workspace;
+class OpenGl_Structure;
+typedef NCollection_IndexedMap<const OpenGl_Structure*> OpenGl_IndexedMapOfStructure;
+
+//! Class storing the frame statistics.
+class OpenGl_FrameStats : public Standard_Transient
+{
+ DEFINE_STANDARD_RTTIEXT(OpenGl_FrameStats, Standard_Transient)
+public:
+
+ //! Stats counter.
+ enum Counter
+ {
+ Counter_NbLayers = 0, //!< number of ZLayers
+ Counter_NbLayersNotCulled, //!< number of not culled ZLayers
+ Counter_NbStructs, //!< number of defined OpenGl_Structure
+ Counter_NbStructsNotCulled, //!< number of not culled OpenGl_Structure
+ Counter_NbGroupsNotCulled, //!< number of not culled OpenGl_Group
+ Counter_NbElemsNotCulled, //!< number of not culled OpenGl_Element
+ Counter_NbElemsFillNotCulled, //!< number of not culled OpenGl_PrimitiveArray drawing triangles
+ Counter_NbElemsLineNotCulled, //!< number of not culled OpenGl_PrimitiveArray drawing lines
+ Counter_NbElemsPointNotCulled, //!< number of not culled OpenGl_PrimitiveArray drawing points
+ Counter_NbElemsTextNotCulled, //!< number of not culled OpenGl_Text
+ Counter_NbTrianglesNotCulled, //!< number of not culled (as structure) triangles
+ Counter_NbPointsNotCulled, //!< number of not culled (as structure) points
+ Counter_EstimatedBytesGeom, //!< estimated GPU memory used for geometry
+ Counter_EstimatedBytesFbos, //!< estimated GPU memory used for FBOs
+ Counter_EstimatedBytesTextures, //!< estimated GPU memory used for textures
+ };
+ enum { Counter_NB = Counter_EstimatedBytesTextures + 1 };
+
+public:
+
+ //! Default constructor.
+ Standard_EXPORT OpenGl_FrameStats();
+
+ //! Destructor.
+ Standard_EXPORT virtual ~OpenGl_FrameStats();
+
+ //! Returns interval in seconds for updating meters across several frames; 1 second by default.
+ Standard_Real UpdateInterval() const { return myUpdateInterval; }
+
+ //! Sets interval in seconds for updating values.
+ void SetUpdateInterval (Standard_Real theInterval) { myUpdateInterval = theInterval; }
+
+ //! Prefer longer lines over more greater of lines.
+ Standard_Boolean IsLongLineFormat() const { return myIsLongLineFormat; }
+
+ //! Set if format should prefer longer lines over greater number of lines.
+ void SetLongLineFormat (Standard_Boolean theValue) { myIsLongLineFormat = theValue; }
+
+ //! Frame redraw started.
+ Standard_EXPORT virtual void FrameStart (const Handle(OpenGl_Workspace)& theWorkspace = Handle(OpenGl_Workspace)());
+
+ //! Frame redraw finished.
+ Standard_EXPORT virtual void FrameEnd (const Handle(OpenGl_Workspace)& theWorkspace = Handle(OpenGl_Workspace)());
+
+public:
+
+ //! Returns formatted string.
+ Standard_EXPORT virtual TCollection_AsciiString FormatStats (Graphic3d_RenderingParams::PerfCounters theFlags) const;
+
+ //! Returns duration of the last frame in seconds.
+ Standard_Real FrameDuration() const { return myFrameDuration; }
+
+ //! Returns FPS (frames per seconds, elapsed time).
+ //! This number indicates an actual frame rate averaged for several frames within UpdateInterval() duration,
+ //! basing on a real elapsed time between updates.
+ Standard_Real FrameRate() const { return myFps; }
+
+ //! Returns CPU FPS (frames per seconds, CPU time).
+ //! This number indicates a PREDICTED frame rate,
+ //! basing on CPU elapsed time between updates and NOT real elapsed time (which might include periods of CPU inactivity).
+ //! Number is expected to be greater then actual frame rate returned by FrameRate().
+ //! Values significantly greater actual frame rate indicate that rendering is limited by GPU performance (CPU is stalled in-between),
+ //! while values around actual frame rate indicate rendering being limited by CPU performance (GPU is stalled in-between).
+ Standard_Real FrameRateCpu() const { return myFpsCpu; }
+
+ //! Returns value of specified counter, cached between stats updates.
+ //! Should NOT be called between ::FrameStart() and ::FrameEnd() calls.
+ Standard_Size CounterValue (OpenGl_FrameStats::Counter theCounter) const { return myCounters[theCounter]; }
+
+ //! Returns TRUE if some Layers have been culled.
+ Standard_Boolean HasCulledLayers() const { return myCounters[Counter_NbLayersNotCulled] != myCounters[Counter_NbLayers]; }
+
+ //! Returns TRUE if some structures have been culled.
+ Standard_Boolean HasCulledStructs() const { return myCounters[Counter_NbStructsNotCulled] != myCounters[Counter_NbStructs]; }
+
+public:
+
+ //! Returns TRUE if this stats are equal to another.
+ virtual Standard_Boolean IsEqual (const Handle(OpenGl_FrameStats)& theOther) const
+ {
+ // check just a couple of major counters
+ return Abs (myFps - theOther->myFps) <= 0.001
+ && Abs (myFpsCpu - theOther->myFpsCpu) <= 0.001
+ && myCounters[Counter_NbLayers] == theOther->myCounters[Counter_NbLayers]
+ && myCounters[Counter_NbLayersNotCulled] == theOther->myCounters[Counter_NbLayersNotCulled]
+ && myCounters[Counter_NbStructs] == theOther->myCounters[Counter_NbStructs]
+ && myCounters[Counter_NbStructsNotCulled] == theOther->myCounters[Counter_NbStructsNotCulled];
+ }
+
+ //! Copy stats values from another instance
+ virtual void CopyFrom (const Handle(OpenGl_FrameStats)& theOther)
+ {
+ myFps = theOther->myFps;
+ myFpsCpu = theOther->myFpsCpu;
+ memcpy (myCounters, theOther->myCounters, sizeof(myCounters));
+ }
+
+ //! Returns value of specified counter for modification, should be called between ::FrameStart() and ::FrameEnd() calls.
+ Standard_Size& ChangeCounter (OpenGl_FrameStats::Counter theCounter) { return myCountersTmp[theCounter]; }
+
+protected:
+
+ //! Updates counters for structures.
+ Standard_EXPORT virtual void updateStructures (const OpenGl_IndexedMapOfStructure& theStructures,
+ Standard_Boolean theToCountElems,
+ Standard_Boolean theToCountTris,
+ Standard_Boolean theToCountMem);
+
+protected:
+
+ OSD_Timer myFpsTimer; //!< timer for FPS measurements
+ Standard_Real myFrameStartTime; //!< time at the beginning of frame redraw
+ Standard_Real myFrameDuration; //!< frame duration
+ Standard_Real myFps; //!< FPS meter (frames per seconds, elapsed time)
+ Standard_Real myFpsCpu; //!< CPU FPS meter (frames per seconds, CPU time)
+ Standard_Real myUpdateInterval; //!< interval to update meters
+ Standard_Size myFpsFrameCount; //!< FPS counter (within short measurement time slice)
+ Standard_Size myCounters [Counter_NB]; //!< counter values cached between updates
+ Standard_Size myCountersTmp[Counter_NB]; //!< counter values filled during
+ Standard_Boolean myIsLongLineFormat; //!< prefer longer lines over greater number of lines
+
+};
+
+DEFINE_STANDARD_HANDLE(OpenGl_FrameStats, Standard_Transient)
+
+#endif // _OpenGl_FrameStats_HeaderFile
--- /dev/null
+// 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 <OpenGl_FrameStatsPrs.hxx>
+
+#include <OpenGl_View.hxx>
+#include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_Workspace.hxx>
+
+// =======================================================================
+// function : OpenGl_FrameStatsPrs
+// purpose :
+// =======================================================================
+OpenGl_FrameStatsPrs::OpenGl_FrameStatsPrs()
+: myStatsPrev (new OpenGl_FrameStats())
+{
+ myParams.HAlign = Graphic3d_HTA_CENTER;
+ myParams.VAlign = Graphic3d_VTA_CENTER;
+ myHasPlane = false;
+}
+
+// =======================================================================
+// function : ~OpenGl_FrameStatsPrs
+// purpose :
+// =======================================================================
+OpenGl_FrameStatsPrs::~OpenGl_FrameStatsPrs()
+{
+ //
+}
+
+// =======================================================================
+// function : Release
+// purpose :
+// =======================================================================
+void OpenGl_FrameStatsPrs::Release (OpenGl_Context* theCtx)
+{
+ OpenGl_Text::Release (theCtx);
+}
+
+// =======================================================================
+// function : Update
+// purpose :
+// =======================================================================
+void OpenGl_FrameStatsPrs::Update (const Handle(OpenGl_Workspace)& theWorkspace)
+{
+ const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+ const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
+ const Graphic3d_RenderingParams& aRendParams = theWorkspace->View()->RenderingParams();
+ myTrsfPers = theWorkspace->View()->RenderingParams().StatsPosition;
+ myTextAspect.SetAspect (aRendParams.StatsTextAspect);
+
+ // adjust text alignment depending on corner
+ const OpenGl_TextParam aParamsPrev = myParams;
+ myParams.Height = aRendParams.StatsTextHeight;
+ myParams.HAlign = Graphic3d_HTA_CENTER;
+ myParams.VAlign = Graphic3d_VTA_CENTER;
+ if (!myTrsfPers.IsNull() && (myTrsfPers->Corner2d() & Aspect_TOTP_LEFT) != 0)
+ {
+ myParams.HAlign = Graphic3d_HTA_LEFT;
+ }
+ else if (!myTrsfPers.IsNull() && (myTrsfPers->Corner2d() & Aspect_TOTP_RIGHT) != 0)
+ {
+ myParams.HAlign = Graphic3d_HTA_RIGHT;
+ }
+ if (!myTrsfPers.IsNull() && (myTrsfPers->Corner2d() & Aspect_TOTP_TOP) != 0)
+ {
+ myParams.VAlign = Graphic3d_VTA_TOP;
+ }
+ else if (!myTrsfPers.IsNull() && (myTrsfPers->Corner2d() & Aspect_TOTP_BOTTOM) != 0)
+ {
+ myParams.VAlign = Graphic3d_VTA_BOTTOM;
+ }
+ if (myParams.Height != aParamsPrev.Height
+ || myParams.HAlign != aParamsPrev.HAlign
+ || myParams.VAlign != aParamsPrev.VAlign)
+ {
+ Release (aCtx.operator->());
+ }
+
+ if (myStatsPrev->IsEqual (aStats)
+ && !myString.IsEmpty())
+ {
+ return;
+ }
+
+ myStatsPrev->CopyFrom (aStats);
+ const TCollection_AsciiString aText = aStats->FormatStats (aRendParams.CollectedStats);
+
+ releaseVbos (aCtx.operator->());
+ myString.FromUnicode (aText.ToCString());
+}
+
+// =======================================================================
+// function : Render
+// purpose :
+// =======================================================================
+void OpenGl_FrameStatsPrs::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
+{
+ const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+ const Standard_Boolean wasEnabledDepth = theWorkspace->UseDepthWrite();
+ if (theWorkspace->UseDepthWrite())
+ {
+ theWorkspace->UseDepthWrite() = Standard_False;
+ glDepthMask (GL_FALSE);
+ }
+
+ aCtx->ModelWorldState.Push();
+ aCtx->ModelWorldState.ChangeCurrent().InitIdentity();
+
+ aCtx->WorldViewState.Push();
+ OpenGl_Mat4& aWorldView = aCtx->WorldViewState.ChangeCurrent();
+ if (!myTrsfPers.IsNull())
+ {
+ myTrsfPers->Apply (theWorkspace->View()->Camera(),
+ aCtx->ProjectionState.Current(), aWorldView,
+ aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
+ }
+
+ aCtx->ApplyModelViewMatrix();
+
+ const OpenGl_AspectText* aTextAspectBack = theWorkspace->SetAspectText (&myTextAspect);
+ OpenGl_Text::Render (theWorkspace);
+ theWorkspace->SetAspectText (aTextAspectBack);
+
+ aCtx->WorldViewState.Pop();
+ aCtx->ModelWorldState.Pop();
+ aCtx->ApplyWorldViewMatrix();
+
+ if (theWorkspace->UseDepthWrite() != wasEnabledDepth)
+ {
+ theWorkspace->UseDepthWrite() = wasEnabledDepth;
+ glDepthMask (wasEnabledDepth ? GL_TRUE : GL_FALSE);
+ }
+}
--- /dev/null
+// 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.
+
+#ifndef _OpenGl_FrameStatsPrs_HeaderFile
+#define _OpenGl_FrameStatsPrs_HeaderFile
+
+#include <OpenGl_FrameStats.hxx>
+#include <OpenGl_Text.hxx>
+
+class Graphic3d_TransformPers;
+
+//! Element rendering frame statistics.
+class OpenGl_FrameStatsPrs : public OpenGl_Text
+{
+public:
+
+ //! Default constructor.
+ Standard_EXPORT OpenGl_FrameStatsPrs();
+
+ //! Destructor
+ Standard_EXPORT virtual ~OpenGl_FrameStatsPrs();
+
+ //! Render element.
+ Standard_EXPORT virtual void Render (const Handle(OpenGl_Workspace)& theWorkspace) const Standard_OVERRIDE;
+
+ //! Release OpenGL resources.
+ Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
+
+ //! Update text.
+ Standard_EXPORT void Update (const Handle(OpenGl_Workspace)& theWorkspace);
+
+ //! Assign text aspect.
+ void SetTextAspect (const Handle(Graphic3d_AspectText3d)& theAspect) { myTextAspect.SetAspect (theAspect); }
+
+protected:
+
+ OpenGl_AspectText myTextAspect; //!< text aspect
+ Handle(Graphic3d_TransformPers) myTrsfPers; //!< transformation persistence
+ Handle(OpenGl_FrameStats) myStatsPrev; //!< currently displayed stats
+
+};
+
+#endif // _OpenGl_FrameStatsPrs_HeaderFile
const Handle(Select3D_BVHBuilder3d)& theBuilder)
: myArray (0, theNbPriorities - 1),
myNbStructures (0),
+ myNbStructuresNotCulled (0),
myBVHPrimitivesTrsfPers (theBuilder),
myBVHIsLeftChildQueuedFirst (Standard_True),
- myIsBVHPrimitivesNeedsReset (Standard_False),
- myIsCulled (Standard_False)
+ myIsBVHPrimitivesNeedsReset (Standard_False)
{
myIsBoundingBoxNeedsReset[0] = myIsBoundingBoxNeedsReset[1] = true;
}
{
updateBVH();
- myIsCulled = false;
- for (OpenGl_ArrayOfIndexedMapOfStructure::Iterator aMapIter (myArray); aMapIter.More(); aMapIter.Next())
+ myNbStructuresNotCulled = myNbStructures;
+ for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitives.Structures()); aStructIter.More(); aStructIter.Next())
{
- const OpenGl_IndexedMapOfStructure& aStructures = aMapIter.Value();
- for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (aStructures); aStructIter.More(); aStructIter.Next())
- {
- const OpenGl_Structure* aStruct = aStructIter.Value();
- aStruct->SetCulled (theToTraverse);
- }
+ const OpenGl_Structure* aStruct = aStructIter.Value();
+ aStruct->SetCulled (theToTraverse);
+ }
+ for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (myBVHPrimitivesTrsfPers.Structures()); aStructIter.More(); aStructIter.Next())
+ {
+ const OpenGl_Structure* aStruct = aStructIter.Value();
+ aStruct->SetCulled (theToTraverse);
}
if (!theToTraverse)
return;
}
- myIsCulled = myAlwaysRenderedMap.IsEmpty();
+ myNbStructuresNotCulled = myAlwaysRenderedMap.Extent();
OpenGl_BVHTreeSelector::CullingContext aCullCtx;
theSelector.SetCullingDistance(aCullCtx, myLayerSettings.CullingDistance());
theSelector.SetCullingSize (aCullCtx, myLayerSettings.CullingSize());
continue;
}
- myIsCulled = false;
Standard_Integer aStack[BVH_Constants_MaxTreeDepth];
Standard_Integer aHead = -1;
Standard_Integer aNode = 0; // a root node
? myBVHPrimitivesTrsfPers.GetStructureById (aIdx)
: myBVHPrimitives.GetStructureById (aIdx);
aStruct->MarkAsNotCulled();
+ ++myNbStructuresNotCulled;
if (aHead < 0)
{
break;
//! @return the number of structures
Standard_Integer NbStructures() const { return myNbStructures; }
+ //! Number of NOT culled structures in the layer.
+ Standard_Integer NbStructuresNotCulled() const { return myNbStructuresNotCulled; }
+
//! Returns the number of available priority levels
Standard_Integer NbPriorities() const { return myArray.Length(); }
const Standard_Boolean theToTraverse);
//! Returns TRUE if layer is empty or has been discarded entirely by culling test.
- bool IsCulled() const { return myNbStructures == 0 || myIsCulled; }
+ bool IsCulled() const { return myNbStructuresNotCulled == 0; }
// Render all structures.
void Render (const Handle(OpenGl_Workspace)& theWorkspace,
return myBVHPrimitivesTrsfPers.Size();
}
+public:
+
+ //! Returns set of OpenGl_Structures structures for building BVH tree.
+ const OpenGl_BVHClipPrimitiveSet& CullableStructuresBVH() const { return myBVHPrimitives; }
+
+ //! Returns set of transform persistent OpenGl_Structures for building BVH tree.
+ const OpenGl_BVHClipPrimitiveTrsfPersSet& CullableTrsfPersStructuresBVH() const { return myBVHPrimitivesTrsfPers; }
+
+ //! Returns indexed map of always rendered structures.
+ const NCollection_IndexedMap<const OpenGl_Structure*>& NonCullableStructures() const { return myAlwaysRenderedMap; }
+
protected:
//! Updates BVH trees if their state has been invalidated.
- void updateBVH() const;
+ Standard_EXPORT void updateBVH() const;
//! Iterates through the hierarchical list of existing structures and renders them all.
- void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const;
+ Standard_EXPORT void renderAll (const Handle(OpenGl_Workspace)& theWorkspace) const;
private:
//! Overall number of structures rendered in the layer.
Standard_Integer myNbStructures;
+ //! Number of NOT culled structures in the layer.
+ Standard_Integer myNbStructuresNotCulled;
+
//! Layer setting flags.
Graphic3d_ZLayerSettings myLayerSettings;
//! Defines if the cached bounding box is outdated.
mutable bool myIsBoundingBoxNeedsReset[2];
- //! Flag indicating that this layer is marked culled as whole
- bool myIsCulled;
-
//! Cached layer bounding box.
mutable Bnd_Box myBoundingBox[2];
//! Release GL resources.
virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage - not implemented.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE { return 0; }
+
//! Index of currently selected type of hatch.
int TypeOfHatch() const { return myTypeOfHatch; }
case 10: myVboAttribs = new OpenGl_VertexBufferT<OpenGl_VertexBuffer, 10>(*myAttribs); break;
}
- if (!myVboAttribs->init (theCtx, 0, myAttribs->NbElements, myAttribs->Data(), GL_NONE, myAttribs->Stride))
+ // specify data type as Byte and NbComponents as Stride, so that OpenGl_VertexBuffer::EstimatedDataSize() will return correct value
+ if (!myVboAttribs->init (theCtx, myAttribs->Stride, myAttribs->NbElements, myAttribs->Data(), GL_UNSIGNED_BYTE, myAttribs->Stride))
{
TCollection_ExtendedString aMsg;
aMsg += "VBO creation for Primitive Array has failed for ";
const Handle(Graphic3d_Buffer)& theAttribs,
const Handle(Graphic3d_BoundBuffer)& theBounds);
+public:
+
+ //! Returns index VBO.
+ const Handle(OpenGl_VertexBuffer)& IndexVbo() const { return myVboIndices; }
+
+ //! Returns attributes VBO.
+ const Handle(OpenGl_VertexBuffer)& AttributesVbo() const { return myVboAttribs; }
+
protected:
//! VBO initialization procedures
//! @param theGlCtx - bound GL context, shouldn't be NULL.
Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) = 0;
+ //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
+ virtual Standard_Size EstimatedDataSize() const = 0;
+
private:
//! Copy should be performed only within Handles!
//! Destroys object - will release GPU memory if any.
Standard_EXPORT virtual void Release (OpenGl_Context* theContext) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage - not implemented.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE { return 0; }
+
//! Creates an uninitialized sampler object.
Standard_EXPORT Standard_Boolean Create (const Handle(OpenGl_Context)& theContext);
//! Destroys shader object.
Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage - not implemented.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE { return 0; }
+
//! Returns type of shader object.
GLenum Type() const { return myType; }
//! Destroys shader program.
Standard_EXPORT virtual void Release (OpenGl_Context* theCtx) Standard_OVERRIDE;
+ //! Returns estimated GPU memory usage - cannot be easily estimated.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE { return 0; }
+
//! Attaches shader object to the program object.
Standard_EXPORT Standard_Boolean AttachShader (const Handle(OpenGl_Context)& theCtx,
const Handle(OpenGl_ShaderObject)& theShader);
//! Releases structure resources.
virtual void Release (const Handle(OpenGl_Context)& theGlCtx);
- //! Marks structure as culled/not culled.
- void SetCulled (Standard_Boolean theIsCulled) const
- {
- myIsCulled = theIsCulled && !IsAlwaysRendered();
- }
+ //! Marks structure as culled/not culled - note that IsAlwaysRendered() is ignored here!
+ void SetCulled (Standard_Boolean theIsCulled) const { myIsCulled = theIsCulled; }
//! Marks structure as overlapping the current view volume one.
//! The method is called during traverse of BVH tree.
friend class OpenGl_Trihedron;
friend class OpenGl_GraduatedTrihedron;
-private:
-
//! Release cached VBO resources
- void releaseVbos (OpenGl_Context* theCtx);
+ Standard_EXPORT void releaseVbos (OpenGl_Context* theCtx);
+
+private:
//! Setup matrix.
void setupMatrix (const Handle(OpenGl_Context)& theCtx,
mySizeY (0),
mySizeZ (0),
myTextFormat (GL_RGBA),
+ mySizedFormat(GL_RGBA8),
+ myNbSamples (1),
myHasMipmaps (Standard_False),
myIsAlpha (false)
{
myHasMipmaps = toCreateMipMaps;
myTextFormat = thePixelFormat;
+ mySizedFormat = theTextFormat;
+ myNbSamples = 1;
#if !defined(GL_ES_VERSION_2_0)
const GLint anIntFormat = theTextFormat;
#else
theSizeX, 0,
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_1D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
if (aTestWidth == 0)
{
// no memory or broken input parameters
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
if (aTestWidth == 0 || aTestHeight == 0)
{
// no memory or broken input parameters
thePixelFormat, theDataType, NULL);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &aTestWidth);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &aTestHeight);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
if (aTestWidth == 0 || aTestHeight == 0)
{
// no memory or broken input parameters
return false;
}
- const GLsizei aNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
+ myNbSamples = OpenGl_Context::GetPowerOfTwo (theNbSamples, theCtx->MaxMsaaSamples());
myTarget = GL_TEXTURE_2D_MULTISAMPLE;
+ myHasMipmaps = false;
if(theSizeX > theCtx->MaxTextureSize()
|| theSizeY > theCtx->MaxTextureSize())
{
Bind (theCtx);
//myTextFormat = theTextFormat;
+ mySizedFormat = theTextFormat;
#if !defined(GL_ES_VERSION_2_0)
if (theCtx->Functions()->glTexStorage2DMultisample != NULL)
{
- theCtx->Functions()->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+ theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
}
else
{
- theCtx->Functions()->glTexImage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+ theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
}
#else
- theCtx->Functions() ->glTexStorage2DMultisample (myTarget, aNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
+ theCtx->Functions() ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
#endif
if (theCtx->core11fwd->glGetError() != GL_NO_ERROR)
{
#if !defined(GL_ES_VERSION_2_0)
myTarget = GL_TEXTURE_RECTANGLE;
+ myNbSamples = 1;
+ myHasMipmaps = false;
const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
Bind (theCtx);
applyDefaultSamplerParams (theCtx);
- const GLint anIntFormat = theFormat.Internal();
- myTextFormat = theFormat.Format();
+ myTextFormat = theFormat.Format();
+ mySizedFormat = theFormat.Internal();
- glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE,
- 0,
- anIntFormat,
- aSizeX,
- aSizeY,
- 0,
- theFormat.Format(),
- GL_FLOAT,
- NULL);
+ glTexImage2D (GL_PROXY_TEXTURE_RECTANGLE, 0, mySizedFormat,
+ aSizeX, aSizeY, 0,
+ myTextFormat, GL_FLOAT, NULL);
GLint aTestSizeX = 0;
GLint aTestSizeY = 0;
- glGetTexLevelParameteriv (
- GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
- glGetTexLevelParameteriv (
- GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_RECTANGLE, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
if (aTestSizeX == 0 || aTestSizeY == 0)
{
return false;
}
- glTexImage2D (myTarget,
- 0,
- anIntFormat,
- aSizeX,
- aSizeY,
- 0,
- theFormat.Format(),
- GL_FLOAT,
- NULL);
+ glTexImage2D (myTarget, 0, mySizedFormat,
+ aSizeX, aSizeY, 0,
+ myTextFormat, GL_FLOAT, NULL);
if (glGetError() != GL_NO_ERROR)
{
}
myTarget = GL_TEXTURE_3D;
+ myNbSamples = 1;
+ myHasMipmaps = false;
const GLsizei aSizeX = Min (theCtx->MaxTextureSize(), theSizeX);
const GLsizei aSizeY = Min (theCtx->MaxTextureSize(), theSizeY);
return false;
}
- const GLint anIntFormat = theTextFormat;
+ mySizedFormat = theTextFormat;
#if !defined (GL_ES_VERSION_2_0)
- theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D,
- 0,
- anIntFormat,
- aSizeX,
- aSizeY,
- aSizeZ,
- 0,
- thePixelFormat,
- theDataType,
- NULL);
+ theCtx->core15fwd->glTexImage3D (GL_PROXY_TEXTURE_3D, 0, mySizedFormat,
+ aSizeX, aSizeY, aSizeZ, 0,
+ thePixelFormat, theDataType, NULL);
GLint aTestSizeX = 0;
GLint aTestSizeY = 0;
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_WIDTH, &aTestSizeX);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_HEIGHT, &aTestSizeY);
glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_DEPTH, &aTestSizeZ);
+ glGetTexLevelParameteriv (GL_PROXY_TEXTURE_3D, 0, GL_TEXTURE_INTERNAL_FORMAT, &mySizedFormat);
if (aTestSizeX == 0 || aTestSizeY == 0 || aTestSizeZ == 0)
{
#endif
applyDefaultSamplerParams (theCtx);
- theCtx->Functions()->glTexImage3D (myTarget,
- 0,
- anIntFormat,
- aSizeX,
- aSizeY,
- aSizeZ,
- 0,
- thePixelFormat,
- theDataType,
- thePixels);
+ theCtx->Functions()->glTexImage3D (myTarget, 0, mySizedFormat,
+ aSizeX, aSizeY, aSizeZ, 0,
+ thePixelFormat, theDataType, thePixels);
if (glGetError() != GL_NO_ERROR)
{
Unbind (theCtx);
return true;
}
+
+// =======================================================================
+// function : PixelSizeOfPixelFormat
+// purpose :
+// =======================================================================
+Standard_Size OpenGl_Texture::PixelSizeOfPixelFormat (Standard_Integer theInternalFormat)
+{
+ switch(theInternalFormat)
+ {
+ // RED variations (GL_RED, OpenGL 3.0+)
+ case GL_RED:
+ case GL_R8: return 1;
+ case GL_R16: return 2;
+ case GL_R16F: return 2;
+ case GL_R32F: return 4;
+ // RGB variations
+ case GL_RGB: return 3;
+ case GL_RGB8: return 3;
+ case GL_RGB16: return 6;
+ case GL_RGB16F: return 6;
+ case GL_RGB32F: return 12;
+ // RGBA variations
+ case GL_RGBA: return 4;
+ case GL_RGBA8: return 4;
+ case GL_RGB10_A2: return 4;
+ case GL_RGBA12: return 6;
+ case GL_RGBA16: return 8;
+ case GL_RGBA16F: return 8;
+ case GL_RGBA32F: return 16;
+ //
+ case GL_BGRA_EXT: return 4;
+ // ALPHA variations (deprecated)
+ case GL_ALPHA:
+ case GL_ALPHA8: return 1;
+ case GL_ALPHA16: return 2;
+ case GL_LUMINANCE: return 1;
+ case GL_LUMINANCE_ALPHA: return 2;
+ // depth-stencil
+ case GL_DEPTH24_STENCIL8: return 4;
+ case GL_DEPTH32F_STENCIL8: return 8;
+ case GL_DEPTH_COMPONENT16: return 2;
+ case GL_DEPTH_COMPONENT24: return 3;
+ case GL_DEPTH_COMPONENT32F: return 4;
+ }
+ return 0;
+}
+
+// =======================================================================
+// function : EstimatedDataSize
+// purpose :
+// =======================================================================
+Standard_Size OpenGl_Texture::EstimatedDataSize() const
+{
+ if (!IsValid())
+ {
+ return 0;
+ }
+
+ Standard_Size aSize = PixelSizeOfPixelFormat (mySizedFormat) * mySizeX * myNbSamples;
+ if (mySizeY != 0)
+ {
+ aSize *= Standard_Size(mySizeY);
+ }
+ if (mySizeZ != 0)
+ {
+ aSize *= Standard_Size(mySizeZ);
+ }
+ if (myHasMipmaps)
+ {
+ aSize = aSize + aSize / 3;
+ }
+ return aSize;
+}
//! Helpful constants
static const GLuint NO_TEXTURE = 0;
+ //! Return pixel size of pixel format in bytes.
+ //! Note that this method considers that OpenGL natively supports this pixel format,
+ //! which might be not the case - in the latter case, actual pixel size might differ!
+ Standard_EXPORT static Standard_Size PixelSizeOfPixelFormat (Standard_Integer theInternalFormat);
+
public:
//! Create uninitialized texture.
GLenum& thePixelFormat,
GLenum& theDataType);
+ //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
+ Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
+
protected:
//! Apply default sampler parameters after texture creation.
GLsizei mySizeY; //!< texture height
GLsizei mySizeZ; //!< texture depth
GLenum myTextFormat; //!< texture format - GL_RGB, GL_RGBA,...
+ GLint mySizedFormat;//!< internal (sized) texture format
+ Standard_Integer myNbSamples; //!< number of MSAA samples
Standard_Boolean myHasMipmaps; //!< flag indicates that texture was uploaded with mipmaps
bool myIsAlpha; //!< indicates alpha format
public: //! @name advanced methods
+ //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
+ virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE
+ {
+ return IsValid()
+ ? sizeOfGlType (myDataType) * myComponentsNb * myElemsNb
+ : 0;
+ }
+
//! @return size of specified GL type
static size_t sizeOfGlType (const GLenum theType)
{
void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
{
myGraduatedTrihedron.Release (theCtx.operator->());
+ myFrameStatsPrs.Release (theCtx.operator->());
if (!myTextureEnv.IsNull())
{
#include <OpenGl_BVHTreeSelector.hxx>
#include <OpenGl_Context.hxx>
#include <OpenGl_FrameBuffer.hxx>
+#include <OpenGl_FrameStatsPrs.hxx>
#include <OpenGl_GraduatedTrihedron.hxx>
#include <OpenGl_LayerList.hxx>
#include <OpenGl_LineAttributes.hxx>
//! Renders trihedron.
void renderTrihedron (const Handle(OpenGl_Workspace) &theWorkspace);
+ //! Renders frame statistics.
+ void renderFrameStats();
+
private:
//! Adds the structure to display lists of the view.
OpenGl_BVHTreeSelector myBVHSelector;
OpenGl_GraduatedTrihedron myGraduatedTrihedron;
+ OpenGl_FrameStatsPrs myFrameStatsPrs;
Handle(OpenGl_TextureSet) myTextureEnv;
friend class OpenGl_GraphicDriver;
friend class OpenGl_Workspace;
friend class OpenGl_LayerList;
+ friend class OpenGl_FrameStats;
};
#endif // _OpenGl_View_Header
#include <OpenGl_AspectLine.hxx>
#include <OpenGl_Context.hxx>
+#include <OpenGl_FrameStats.hxx>
#include <OpenGl_Matrix.hxx>
#include <OpenGl_Workspace.hxx>
#include <OpenGl_View.hxx>
const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
+ aCtx->FrameStats()->FrameStart (myWorkspace);
// release pending GL resources
aCtx->ReleaseDelayed();
// reset render mode state
aCtx->FetchState();
+ aCtx->FrameStats()->FrameEnd (myWorkspace);
myWasRedrawnGL = Standard_True;
}
const Graphic3d_StereoMode aStereoMode = myRenderParams.StereoMode;
Graphic3d_Camera::Projection aProjectType = myCamera->ProjectionType();
OpenGl_FrameBuffer* aFrameBuffer = myFBO.operator->();
+ aCtx->FrameStats()->FrameStart (myWorkspace);
if ( aFrameBuffer == NULL
&& !aCtx->DefaultFrameBuffer().IsNull()
{
aCtx->core11fwd->glFlush();
}
+ aCtx->FrameStats()->FrameEnd (myWorkspace);
myWasRedrawnGL = Standard_True;
}
glDisable (GL_CULL_FACE);
}
}
+ else
+ {
+ renderFrameStats();
+ }
// reset FFP state for safety
aContext->BindProgram (Handle(OpenGl_ShaderProgram)());
}
}
+//=======================================================================
+//function : renderFrameStats
+//purpose :
+//=======================================================================
+void OpenGl_View::renderFrameStats()
+{
+ if (myRenderParams.ToShowStats
+ && myRenderParams.CollectedStats != Graphic3d_RenderingParams::PerfCounters_NONE)
+ {
+ myFrameStatsPrs.Update (myWorkspace);
+ myFrameStatsPrs.Render (myWorkspace);
+ }
+}
+
// =======================================================================
// function : Invalidate
// purpose :
return 0;
}
+//! Read Graphic3d_RenderingParams::PerfCounters flag.
+static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
+ Standard_Boolean& theToReset,
+ Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
+ Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
+{
+ Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
+ TCollection_AsciiString aVal = theValue;
+ Standard_Boolean toReverse = Standard_False;
+ if (aVal == "none")
+ {
+ theToReset = Standard_True;
+ return Standard_True;
+ }
+ else if (aVal.StartsWith ("-"))
+ {
+ toReverse = Standard_True;
+ aVal = aVal.SubString (2, aVal.Length());
+ }
+ else if (aVal.StartsWith ("no"))
+ {
+ toReverse = Standard_True;
+ aVal = aVal.SubString (3, aVal.Length());
+ }
+ else if (aVal.StartsWith ("+"))
+ {
+ aVal = aVal.SubString (2, aVal.Length());
+ }
+ else
+ {
+ theToReset = Standard_True;
+ }
+
+ if ( aVal == "fps"
+ || aVal == "framerate") aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
+ else if (aVal == "cpu") aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
+ else if (aVal == "layers") aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
+ else if (aVal == "structs"
+ || aVal == "structures"
+ || aVal == "objects") aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
+ else if (aVal == "groups") aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
+ else if (aVal == "arrays") aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
+ else if (aVal == "tris"
+ || aVal == "triangles") aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
+ else if (aVal == "pnts"
+ || aVal == "points") aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
+ else if (aVal == "mem"
+ || aVal == "gpumem"
+ || aVal == "estimmem") aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
+ else if (aVal == "basic") aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
+ else if (aVal == "extended"
+ || aVal == "verbose"
+ || aVal == "extra") aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
+ else
+ {
+ return Standard_False;
+ }
+
+ if (toReverse)
+ {
+ theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
+ }
+ else
+ {
+ theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
+ }
+ return Standard_True;
+}
+
+//! Read Graphic3d_RenderingParams::PerfCounters flags.
+static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
+ Graphic3d_RenderingParams::PerfCounters& theFlags)
+{
+ TCollection_AsciiString aValue = theValue;
+ Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
+ Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
+ Standard_Boolean toReset = Standard_False;
+ for (;;)
+ {
+ Standard_Integer aSplitPos = aValue.Search ("|");
+ if (aSplitPos <= 0)
+ {
+ if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
+ {
+ return Standard_False;
+ }
+ if (toReset)
+ {
+ theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
+ }
+ theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags | aFlagsAdd);
+ theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
+ return Standard_True;
+ }
+
+ if (aSplitPos > 1)
+ {
+ TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
+ if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
+ {
+ return Standard_False;
+ }
+ }
+ aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
+ }
+}
+
//=======================================================================
//function : VRenderParams
//purpose : Enables/disables rendering features
case V3d_GOURAUD: theDI << "gouraud"; break;
case V3d_PHONG: theDI << "phong"; break;
}
+ {
+ theDI << "perfCounters:";
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
+ {
+ theDI << " fps";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
+ {
+ theDI << " cpu";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
+ {
+ theDI << " structs";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
+ {
+ theDI << " groups";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
+ {
+ theDI << " arrays";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
+ {
+ theDI << " tris";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
+ {
+ theDI << " pnts";
+ }
+ if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
+ {
+ theDI << " gpumem";
+ }
+ if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
+ {
+ theDI << " none";
+ }
+ theDI << "\n";
+ }
theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass ? "on" : "off") << "\n";
theDI << "\n";
return 0;
return 1;
}
}
+ else if (aFlag == "-performancestats"
+ || aFlag == "-performancecounters"
+ || aFlag == "-perfstats"
+ || aFlag == "-perfcounters"
+ || aFlag == "-stats")
+ {
+ if (++anArgIter >= theArgNb)
+ {
+ std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+ return 1;
+ }
+
+ TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
+ aFlagsStr.LowerCase();
+ Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
+ if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
+ {
+ std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+ return 1;
+ }
+ aView->ChangeRenderingParams().CollectedStats = aFlags;
+ aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
+ }
+ else if (aFlag == "-perfupdateinterval"
+ || aFlag == "-statsupdateinterval")
+ {
+ if (++anArgIter >= theArgNb)
+ {
+ std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+ return 1;
+ }
+ aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
+ }
else
{
std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
"\n '-exposure value' Exposure value for tone mapping (0.0 value disables the effect)"
"\n '-whitepoint value' White point value for filmic tone mapping"
"\n '-tonemapping mode' Tone mapping mode (disabled, filmic)"
+ "\n '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points|gpuMem|basic|extended|nofps'"
+ "\n Show/hide performance counters (flags can be combined)"
+ "\n '-perfUpdateInterval nbSeconds' Performance counters update interval"
"\n Unlike vcaps, these parameters dramatically change visual properties."
"\n Command is intended to control presentation quality depending on"
"\n hardware capabilities and performance.",
# other
array set aSphereNames {}
-set aWithoutClippingSnapshot $imagedir/${casename}_without.png
-set aWithClippingSnapshot $imagedir/${casename}_with.png
-set aDiffImage $imagedir/${casename}_diff.png
-
pload VISUALIZATION MODELING
+vclear
vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT
vactivate small_wnd
+vrenderparams -perfUpdateInterval 0
vfrustumculling 0
vautozfit 0
vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573
vzrange 1 512
-vclear
vremove -all -noinfo
puts [vdrawsphere tmp_sph $SPHERE_FINENESS]
set aSphereNames($i) $aCurrName
}
puts [vfps]
-vdump $aWithoutClippingSnapshot
+vrenderparams -perfCounters none
+vdump $imagedir/${casename}_cull_off_ref.png
+vrenderparams -perfCounters verbose|nofps|nocpu
+vdump $imagedir/${casename}_cull_off.png
puts "All spheres were displayed."
puts ""
vfrustumculling 1
vdisplayall
puts [vfps]
-vdump $aWithClippingSnapshot
+vrenderparams -perfCounters none
+vdump $imagedir/${casename}_cull_on_ref.png
+vrenderparams -perfCounters verbose|nofps|nocpu
+vdump $imagedir/${casename}_cull_on.png
puts "All spheres were displayed."
puts ""
-set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage]
+set aDiffImageResult [diffimage $imagedir/${casename}_cull_on_ref.png $imagedir/${casename}_cull_off_ref.png 0.1 0 0 $imagedir/${casename}_diff.png]
if {$aDiffImageResult != 0} {
puts "ERROR : Test failed: there is a difference between images rendered with and without clipping"
}
-
-verase
# other
array set aBoxNames {}
-set aWithoutClippingSnapshot $imagedir/${casename}_without.png
-set aWithClippingSnapshot $imagedir/${casename}_with.png
-set aDiffImage $imagedir/${casename}_diff.png
-
pload VISUALIZATION MODELING
+vclear
vinit name=small_wnd l=32 t=32 w=$SMALL_WIN_WIDTH h=$SMALL_WIN_HEIGHT
vactivate small_wnd
+vrenderparams -perfUpdateInterval 0
vfrustumculling 0
vautozfit 0
vviewparams -scale 1.953125 -eye 0.57735026918962573 -0.57735026918962573 0.57735026918962573
vzrange 1 512
-vclear
vremove -all -noinfo
set aInnerBoxesNum [expr $BOXES_NUM * $PERCENT_OF_INNER_BOXES / 100]
vdisplay -noupdate $aBoxNames($i)
}
puts [vfps]
-vdump $aWithoutClippingSnapshot
+vrenderparams -perfCounters none
+vdump $imagedir/${casename}_cull_off_ref.png
+vrenderparams -perfCounters verbose|nofps|nocpu
+vdump $imagedir/${casename}_cull_off.png
puts "All boxes were displayed."
puts ""
vdisplay -noupdate $aBoxNames($i)
}
puts [vfps]
-vdump $aWithClippingSnapshot
+vrenderparams -perfCounters none
+vdump $imagedir/${casename}_cull_on_ref.png
+vrenderparams -perfCounters verbose|nofps|nocpu
+vdump $imagedir/${casename}_cull_on.png
puts "All boxes were displayed."
-set aDiffImageResult [diffimage $aWithClippingSnapshot $aWithoutClippingSnapshot 0.1 0 0 $aDiffImage]
+set aDiffImageResult [diffimage $imagedir/${casename}_cull_on_ref.png $imagedir/${casename}_cull_off_ref.png 0.1 0 0 $imagedir/${casename}_diff.png]
if {$aDiffImageResult != 0} {
puts "ERROR : Test failed: there is a difference between images rendered with and without clipping"
}
-
-verase