Package: openscenegraph-3.4 / 3.4.0+dfsg1-4

0006-Occlusion-Queries-Stuttering-fix-from-upstream.patch Patch series | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
From: Alberto Luaces <aluaces@udc.es>
Date: Wed, 21 Sep 2016 20:51:59 +0200
Subject: Occlusion Queries Stuttering fix from upstream.

---
 include/osg/OcclusionQueryNode |   4 +-
 src/osg/OcclusionQueryNode.cpp | 105 +++++++++++++++++++++++------------------
 2 files changed, 60 insertions(+), 49 deletions(-)

diff --git a/include/osg/OcclusionQueryNode b/include/osg/OcclusionQueryNode
index 07285f8..2b68e4c 100644
--- a/include/osg/OcclusionQueryNode
+++ b/include/osg/OcclusionQueryNode
@@ -40,7 +40,7 @@ osg::StateSet* initOQDebugState();
 class TestResult : public osg::Referenced
 {
 public:
-    TestResult() : _init( false ), _id( 0 ), _contextID( 0 ), _active( false ), _numPixels( 0 ) {}
+    TestResult() : _init( false ), _id( 0 ), _contextID( 0 ), _active( false ), _numPixels( 0 ) {setThreadSafeRefUnref(true);}
     ~TestResult() {}
 
     bool _init;
@@ -81,7 +81,7 @@ public:
     static void discardDeletedQueryObjects( unsigned int contextID );
 
 protected:
-    typedef std::map< const osg::Camera*, TestResult > ResultMap;
+    typedef std::map< const osg::Camera*, osg::ref_ptr<osg::TestResult> > ResultMap;
     mutable ResultMap _results;
     mutable OpenThreads::Mutex _mapMutex;
 
diff --git a/src/osg/OcclusionQueryNode.cpp b/src/osg/OcclusionQueryNode.cpp
index 1deaf8c..b95f86a 100644
--- a/src/osg/OcclusionQueryNode.cpp
+++ b/src/osg/OcclusionQueryNode.cpp
@@ -97,7 +97,7 @@ StateSet* initOQDebugState()
 
 struct RetrieveQueriesCallback : public osg::Camera::DrawCallback
 {
-    typedef std::vector<osg::TestResult*> ResultsVector;
+    typedef std::vector<osg::ref_ptr<osg::TestResult> > ResultsVector;
     ResultsVector _results;
 
     RetrieveQueriesCallback( osg::GLExtensions* ext=NULL )
@@ -143,7 +143,7 @@ struct RetrieveQueriesCallback : public osg::Camera::DrawCallback
         ResultsVector::const_iterator it = _results.begin();
         while (it != _results.end())
         {
-            osg::TestResult* tr = const_cast<osg::TestResult*>( *it );
+            osg::TestResult* tr = const_cast<osg::TestResult*>( (*it).get() );
 
             if (!tr->_active || !tr->_init)
             {
@@ -159,31 +159,20 @@ struct RetrieveQueriesCallback : public osg::Camera::DrawCallback
             OSG_DEBUG <<
                 "osgOQ: RQCB: Retrieving..." << std::endl;
 
-#ifdef FORCE_QUERY_RESULT_AVAILABLE_BEFORE_RETRIEVAL
-
-            // Should not need to do this, but is required on some platforms to
-            // work aroung issues in the device driver. For example, without this
-            // code, we've seen crashes on 64-bit Mac/Linux NVIDIA systems doing
-            // multithreaded, multipipe rendering (as in a CAVE).
-            // Tried with ATI and verified this workaround is not needed; the
-            //   problem is specific to NVIDIA.
-            GLint ready( 0 );
-            while( !ready )
+            GLint ready = 0;
+            ext->glGetQueryObjectiv( tr->_id, GL_QUERY_RESULT_AVAILABLE, &ready );
+            if (ready)
             {
-                // Apparently, must actually sleep here to avoid issues w/ NVIDIA Quadro.
-                OpenThreads::Thread::microSleep( 5 );
-                ext->glGetQueryObjectiv( tr->_id, GL_QUERY_RESULT_AVAILABLE, &ready );
-            };
-#endif
-
-            ext->glGetQueryObjectiv( tr->_id, GL_QUERY_RESULT, &(tr->_numPixels) );
-            if (tr->_numPixels < 0)
-                OSG_WARN << "osgOQ: RQCB: " <<
-                "glGetQueryObjectiv returned negative value (" << tr->_numPixels << ")." << std::endl;
-
-            // Either retrieve last frame's results, or ignore it because the
-            //   camera is inside the view. In either case, _active is now false.
-            tr->_active = false;
+                ext->glGetQueryObjectiv( tr->_id, GL_QUERY_RESULT, &(tr->_numPixels) );
+                if (tr->_numPixels < 0)
+                    OSG_WARN << "osgOQ: RQCB: " <<
+                    "glGetQueryObjectiv returned negative value (" << tr->_numPixels << ")." << std::endl;
+
+                // Either retrieve last frame's results, or ignore it because the
+                //   camera is inside the view. In either case, _active is now false.
+                tr->_active = false;
+            }
+            // else: query result not available yet, try again next frame
 
             it++;
             count++;
@@ -196,7 +185,13 @@ struct RetrieveQueriesCallback : public osg::Camera::DrawCallback
 
     void reset()
     {
-        _results.clear();
+        for (ResultsVector::iterator it = _results.begin(); it != _results.end();)
+        {
+            if (!(*it)->_active || !(*it)->_init) // remove results that have already been retrieved or their query objects deleted.
+                it = _results.erase(it);
+            else
+                ++it;
+        }
     }
 
     void add( osg::TestResult* tr )
@@ -264,9 +259,9 @@ QueryGeometry::reset()
     ResultMap::iterator it = _results.begin();
     while (it != _results.end())
     {
-        TestResult& tr = it->second;
-        if (tr._init)
-            QueryGeometry::deleteQueryObject( tr._contextID, tr._id );
+        osg::ref_ptr<TestResult> tr = it->second;
+        if (tr->_init)
+            QueryGeometry::deleteQueryObject( tr->_contextID, tr->_id );
         it++;
     }
     _results.clear();
@@ -294,10 +289,30 @@ QueryGeometry::drawImplementation( osg::RenderInfo& renderInfo ) const
     }
 
     // Get TestResult from Camera map
-    TestResult* tr;
+    osg::ref_ptr<osg::TestResult> tr;
     {
         OpenThreads::ScopedLock<OpenThreads::Mutex> lock( _mapMutex );
-        tr = &( _results[ cam ] );
+        tr = ( _results[ cam ] );
+        if (!tr.valid())
+        {
+            tr = new osg::TestResult;
+            _results[ cam ] = tr;
+        }
+    }
+
+
+    // Issue query
+    if (!tr->_init)
+    {
+        ext->glGenQueries( 1, &(tr->_id) );
+        tr->_contextID = contextID;
+        tr->_init = true;
+    }
+
+    if (tr->_active)
+    {
+        // last query hasn't been retrieved yet
+        return;
     }
 
     // Add TestResult to RQCB.
@@ -310,15 +325,6 @@ QueryGeometry::drawImplementation( osg::RenderInfo& renderInfo ) const
     }
     rqcb->add( tr );
 
-
-    // Issue query
-    if (!tr->_init)
-    {
-        ext->glGenQueries( 1, &(tr->_id) );
-        tr->_contextID = contextID;
-        tr->_init = true;
-    }
-
     OSG_DEBUG <<
         "osgOQ: QG: Querying for: " << _oqnName << std::endl;
 
@@ -349,12 +355,17 @@ QueryGeometry::drawImplementation( osg::RenderInfo& renderInfo ) const
 unsigned int
 QueryGeometry::getNumPixels( const osg::Camera* cam )
 {
-    TestResult tr;
+    osg::ref_ptr<osg::TestResult> tr;
     {
         OpenThreads::ScopedLock<OpenThreads::Mutex> lock( _mapMutex );
         tr =  _results[ cam ];
+        if (!tr.valid())
+        {
+            tr = new osg::TestResult;
+            _results[ cam ] = tr;
+        }
     }
-    return tr._numPixels;
+    return tr->_numPixels;
 }
 
 
@@ -375,11 +386,11 @@ QueryGeometry::releaseGLObjects( osg::State* state ) const
         ResultMap::iterator it = _results.begin();
         while (it != _results.end())
         {
-            TestResult& tr = it->second;
-            if (tr._contextID == contextID)
+            osg::ref_ptr<osg::TestResult> tr = it->second;
+            if (tr->_contextID == contextID)
             {
-                QueryGeometry::deleteQueryObject( contextID, tr._id );
-                tr._init = false;
+                QueryGeometry::deleteQueryObject( contextID, tr->_id );
+                tr->_init = false;
             }
             it++;
         }