0030476: Visualization, Path Tracing - Adaptive Screen Sampling leads to unstable...
[occt.git] / src / OpenGl / OpenGl_FrameStats.cxx
1 // Copyright (c) 2017 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14 #include <OpenGl_FrameStats.hxx>
15
16 #include <OpenGl_GlCore20.hxx>
17 #include <OpenGl_View.hxx>
18 #include <OpenGl_Workspace.hxx>
19
20 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameStats, Graphic3d_FrameStats)
21
22 namespace
23 {
24   //! Return estimated data size.
25   static Standard_Size estimatedDataSize (const Handle(OpenGl_Resource)& theRes)
26   {
27     return !theRes.IsNull() ? theRes->EstimatedDataSize() : 0;
28   }
29 }
30
31 // =======================================================================
32 // function : OpenGl_FrameStats
33 // purpose  :
34 // =======================================================================
35 OpenGl_FrameStats::OpenGl_FrameStats()
36 {
37   //
38 }
39
40 // =======================================================================
41 // function : ~OpenGl_FrameStats
42 // purpose  :
43 // =======================================================================
44 OpenGl_FrameStats::~OpenGl_FrameStats()
45 {
46   //
47 }
48
49 // =======================================================================
50 // function : IsFrameUpdated
51 // purpose  :
52 // =======================================================================
53 bool OpenGl_FrameStats::IsFrameUpdated (Handle(OpenGl_FrameStats)& thePrev) const
54 {
55   const Graphic3d_FrameStatsData& aFrame = LastDataFrame();
56   if (thePrev.IsNull())
57   {
58     thePrev = new OpenGl_FrameStats();
59   }
60   // check just a couple of major counters
61   else if (myLastFrameIndex == thePrev->myLastFrameIndex
62         && Abs (aFrame.FrameRate()    - thePrev->myCountersTmp.FrameRate())    <= 0.001
63         && Abs (aFrame.FrameRateCpu() - thePrev->myCountersTmp.FrameRateCpu()) <= 0.001
64         && aFrame[Graphic3d_FrameStatsCounter_NbLayers]           == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbLayers]
65         && aFrame[Graphic3d_FrameStatsCounter_NbLayersNotCulled]  == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbLayersNotCulled]
66         && aFrame[Graphic3d_FrameStatsCounter_NbStructs]          == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbStructs]
67         && aFrame[Graphic3d_FrameStatsCounter_NbStructsNotCulled] == thePrev->myCountersTmp[Graphic3d_FrameStatsCounter_NbStructsNotCulled])
68   {
69     return false;
70   }
71
72   thePrev->myLastFrameIndex = myLastFrameIndex;
73   thePrev->myCountersTmp = aFrame;
74   return true;
75 }
76
77 // =======================================================================
78 // function : updateStatistics
79 // purpose  :
80 // =======================================================================
81 void OpenGl_FrameStats::updateStatistics (const Handle(Graphic3d_CView)& theView,
82                                           bool theIsImmediateOnly)
83 {
84   const OpenGl_View* aView = dynamic_cast<const OpenGl_View*> (theView.get());
85   if (aView == NULL)
86   {
87     myCounters.SetValue (myLastFrameIndex, myCountersTmp);
88     myCountersTmp.Reset();
89     return;
90   }
91
92   const Graphic3d_RenderingParams::PerfCounters aBits = theView->RenderingParams().CollectedStats;
93   const Standard_Boolean toCountMem     = (aBits & Graphic3d_RenderingParams::PerfCounters_EstimMem)  != 0;
94   const Standard_Boolean toCountTris    = (aBits & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0
95                                        || (aBits & Graphic3d_RenderingParams::PerfCounters_Points)    != 0;
96   const Standard_Boolean toCountElems   = (aBits & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0 || toCountTris || toCountMem;
97   const Standard_Boolean toCountGroups  = (aBits & Graphic3d_RenderingParams::PerfCounters_Groups)      != 0 || toCountElems;
98   const Standard_Boolean toCountStructs = (aBits & Graphic3d_RenderingParams::PerfCounters_Structures)  != 0
99                                        || (aBits & Graphic3d_RenderingParams::PerfCounters_Layers)      != 0 || toCountGroups;
100
101   myCountersTmp[Graphic3d_FrameStatsCounter_NbLayers] = aView->LayerList().Layers().Size();
102   if (toCountStructs
103    || (aBits & Graphic3d_RenderingParams::PerfCounters_Layers)    != 0)
104   {
105     const Standard_Integer aViewId = aView->Identification();
106     for (OpenGl_SequenceOfLayers::Iterator aLayerIter (aView->LayerList().Layers()); aLayerIter.More(); aLayerIter.Next())
107     {
108       const Handle(OpenGl_Layer)& aLayer = aLayerIter.Value();
109       myCountersTmp[Graphic3d_FrameStatsCounter_NbStructs] += aLayer->NbStructures();
110       if (theIsImmediateOnly && !aLayer->LayerSettings().IsImmediate())
111       {
112         continue;
113       }
114
115       if (!aLayer->IsCulled())
116       {
117         ++myCountersTmp[Graphic3d_FrameStatsCounter_NbLayersNotCulled];
118       }
119       myCountersTmp[Graphic3d_FrameStatsCounter_NbStructsNotCulled] += aLayer->NbStructuresNotCulled();
120       if (toCountGroups)
121       {
122         updateStructures (aViewId, aLayer->CullableStructuresBVH().Structures(), toCountElems, toCountTris, toCountMem);
123         updateStructures (aViewId, aLayer->CullableTrsfPersStructuresBVH().Structures(), toCountElems, toCountTris, toCountMem);
124         updateStructures (aViewId, aLayer->NonCullableStructures(), toCountElems, toCountTris, toCountMem);
125       }
126     }
127   }
128   if (toCountMem)
129   {
130     for (OpenGl_Context::OpenGl_ResourcesMap::Iterator aResIter (aView->GlWindow()->GetGlContext()->SharedResources());
131          aResIter.More(); aResIter.Next())
132     {
133       myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesTextures] += aResIter.Value()->EstimatedDataSize();
134     }
135
136     {
137       Standard_Size& aMemFbos = myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesFbos];
138       // main FBOs
139       aMemFbos += estimatedDataSize (aView->myMainSceneFbos[0]);
140       aMemFbos += estimatedDataSize (aView->myMainSceneFbos[1]);
141       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[0]);
142       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbos[1]);
143       // OIT FBOs
144       aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[0]);
145       aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]);
146       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]);
147       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]);
148       // dump FBO
149       aMemFbos += estimatedDataSize (aView->myFBO);
150       // RayTracing FBO
151       aMemFbos += estimatedDataSize (aView->myOpenGlFBO);
152       aMemFbos += estimatedDataSize (aView->myOpenGlFBO2);
153       aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[0]);
154       aMemFbos += estimatedDataSize (aView->myRaytraceFBO1[1]);
155       aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[0]);
156       aMemFbos += estimatedDataSize (aView->myRaytraceFBO2[1]);
157       // also RayTracing
158       aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[0]);
159       aMemFbos += estimatedDataSize (aView->myRaytraceOutputTexture[1]);
160       aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[0]);
161       aMemFbos += estimatedDataSize (aView->myRaytraceVisualErrorTexture[1]);
162       aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[0]);
163       aMemFbos += estimatedDataSize (aView->myRaytraceTileOffsetsTexture[1]);
164       aMemFbos += estimatedDataSize (aView->myRaytraceTileSamplesTexture[0]);
165       aMemFbos += estimatedDataSize (aView->myRaytraceTileSamplesTexture[1]);
166     }
167     {
168       // Ray Tracing geometry
169       Standard_Size& aMemGeom = myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom];
170       aMemGeom += estimatedDataSize (aView->mySceneNodeInfoTexture);
171       aMemGeom += estimatedDataSize (aView->mySceneMinPointTexture);
172       aMemGeom += estimatedDataSize (aView->mySceneMaxPointTexture);
173       aMemGeom += estimatedDataSize (aView->mySceneTransformTexture);
174       aMemGeom += estimatedDataSize (aView->myGeometryVertexTexture);
175       aMemGeom += estimatedDataSize (aView->myGeometryNormalTexture);
176       aMemGeom += estimatedDataSize (aView->myGeometryTexCrdTexture);
177       aMemGeom += estimatedDataSize (aView->myGeometryTriangTexture);
178       aMemGeom += estimatedDataSize (aView->myRaytraceMaterialTexture);
179       aMemGeom += estimatedDataSize (aView->myRaytraceLightSrcTexture);
180     }
181   }
182 }
183
184 // =======================================================================
185 // function : updateStructures
186 // purpose  :
187 // =======================================================================
188 void OpenGl_FrameStats::updateStructures (Standard_Integer theViewId,
189                                           const OpenGl_IndexedMapOfStructure& theStructures,
190                                           Standard_Boolean theToCountElems,
191                                           Standard_Boolean theToCountTris,
192                                           Standard_Boolean theToCountMem)
193 {
194   for (OpenGl_IndexedMapOfStructure::Iterator aStructIter (theStructures); aStructIter.More(); aStructIter.Next())
195   {
196     const OpenGl_Structure* aStruct = aStructIter.Value();
197     const bool isStructHidden = aStruct->IsCulled()
198                             || !aStruct->IsVisible (theViewId);
199     for (; aStruct != NULL; aStruct = aStruct->InstancedStructure())
200     {
201       if (isStructHidden)
202       {
203         if (theToCountMem)
204         {
205           for (OpenGl_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next())
206           {
207             const OpenGl_Group* aGroup = aGroupIter.Value();
208             for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next)
209             {
210               if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast<const OpenGl_PrimitiveArray*> (aNodeIter->elem))
211               {
212                 myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo());
213                 myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo());
214               }
215             }
216           }
217         }
218         continue;
219       }
220
221       myCountersTmp[Graphic3d_FrameStatsCounter_NbGroupsNotCulled] += aStruct->Groups().Size();
222       if (!theToCountElems)
223       {
224         continue;
225       }
226
227       for (OpenGl_Structure::GroupIterator aGroupIter (aStruct->Groups()); aGroupIter.More(); aGroupIter.Next())
228       {
229         const OpenGl_Group* aGroup = aGroupIter.Value();
230         for (const OpenGl_ElementNode* aNodeIter = aGroup->FirstNode(); aNodeIter != NULL; aNodeIter = aNodeIter->next)
231         {
232           if (const OpenGl_PrimitiveArray* aPrim = dynamic_cast<const OpenGl_PrimitiveArray*> (aNodeIter->elem))
233           {
234             ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
235             if (theToCountMem)
236             {
237               myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->AttributesVbo());
238               myCountersTmp[Graphic3d_FrameStatsCounter_EstimatedBytesGeom] += estimatedDataSize (aPrim->IndexVbo());
239             }
240
241             if (aPrim->IsFillDrawMode())
242             {
243               ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsFillNotCulled];
244               if (!theToCountTris)
245               {
246                 continue;
247               }
248
249               const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo();
250               if (anAttribs.IsNull()
251               || !anAttribs->IsValid())
252               {
253                 continue;
254               }
255
256               const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo();
257               const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb();
258               const Standard_Integer aNbBounds  = !aPrim->Bounds().IsNull() ? aPrim->Bounds()->NbBounds : 1;
259               switch (aPrim->DrawMode())
260               {
261                 case GL_TRIANGLES:
262                 {
263                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 3;
264                   break;
265                 }
266                 case GL_TRIANGLE_STRIP:
267                 case GL_TRIANGLE_FAN:
268                 {
269                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 2 * aNbBounds;
270                   break;
271                 }
272                 case GL_TRIANGLES_ADJACENCY:
273                 {
274                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 6;
275                   break;
276                 }
277                 case GL_TRIANGLE_STRIP_ADJACENCY:
278                 {
279                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices - 4 * aNbBounds;
280                   break;
281                 }
282               #if !defined(GL_ES_VERSION_2_0)
283                 case GL_QUADS:
284                 {
285                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += aNbIndices / 2;
286                   break;
287                 }
288                 case GL_QUAD_STRIP:
289                 {
290                   myCountersTmp[Graphic3d_FrameStatsCounter_NbTrianglesNotCulled] += (aNbIndices / 2 - aNbBounds) * 2;
291                   break;
292                 }
293               #endif
294               }
295             }
296             else if (aPrim->DrawMode() == GL_POINTS)
297             {
298               ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsPointNotCulled];
299               if (theToCountTris)
300               {
301                 const Handle(OpenGl_VertexBuffer)& anAttribs = aPrim->AttributesVbo();
302                 if (!anAttribs.IsNull()
303                   && anAttribs->IsValid())
304                 {
305                   const Handle(OpenGl_VertexBuffer)& anIndices = aPrim->IndexVbo();
306                   const Standard_Integer aNbIndices = !anIndices.IsNull() ? anIndices->GetElemsNb() : anAttribs->GetElemsNb();
307                   myCountersTmp[Graphic3d_FrameStatsCounter_NbPointsNotCulled] += aNbIndices;
308                 }
309               }
310             }
311             else
312             {
313               ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsLineNotCulled];
314             }
315           }
316           else if (const OpenGl_Text* aText = dynamic_cast<const OpenGl_Text*> (aNodeIter->elem))
317           {
318             (void )aText;
319             ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsNotCulled];
320             ++myCountersTmp[Graphic3d_FrameStatsCounter_NbElemsTextNotCulled];
321           }
322         }
323       }
324     }
325   }
326 }