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++;
}
|