summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMauro Persano <mauro.persano@kdab.com>2017-05-29 08:58:29 -0300
committerMauro Persano <mauro.persano@kdab.com>2017-05-30 13:20:50 +0000
commit4c9303aa377e45681377997586f0985d5c282bbe (patch)
treed37475fc7ea49096c72f60207f8f4b3f77f17c29 /src
parent95d6847cec8a8c0d5c0013fece507d56c4aee7e6 (diff)
Add reference count for backend buffers
In the main rendering loop, first dirty GL resources are uploaded, then render views are submitted, and then unused GL resources are released. Consider the following piece of code: entity->setParent(nullptr); entity->setParent(root); If this is executed inside a single frame, entity's children buffers will be marked for release when they are removed from the scene, and marked as dirty when they're added again. In the following frame, the render thread will upload them at the beginning of the frame, and incorrectly release them at the end of the frame. This patch adds a reference count for buffers in BufferManager to prevent this kind of race. The reference is incremented when a buffer is added to the scene (in Buffer::initializeFromPeer) and decremented when it's removed from the scene (in BufferFunctor::destroy). Task-number: QTBUG-60726 Change-Id: I8eed7b4c2d8262ba846e73bf4299edae7bc16b3e Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/geometry/buffer.cpp4
-rw-r--r--src/render/geometry/buffermanager.cpp24
-rw-r--r--src/render/geometry/buffermanager_p.h6
3 files changed, 27 insertions, 7 deletions
diff --git a/src/render/geometry/buffer.cpp b/src/render/geometry/buffer.cpp
index 55c86910f..ae2455184 100644
--- a/src/render/geometry/buffer.cpp
+++ b/src/render/geometry/buffer.cpp
@@ -133,6 +133,8 @@ void Buffer::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &chang
Q_ASSERT(m_manager);
if (m_functor)
m_manager->addDirtyBuffer(peerId());
+
+ m_manager->addBufferReference(peerId());
}
void Buffer::forceDataUpload()
@@ -210,7 +212,7 @@ Qt3DCore::QBackendNode *BufferFunctor::get(Qt3DCore::QNodeId id) const
void BufferFunctor::destroy(Qt3DCore::QNodeId id) const
{
- m_manager->addBufferToRelease(id);
+ m_manager->removeBufferReference(id);
return m_manager->releaseResource(id);
}
diff --git a/src/render/geometry/buffermanager.cpp b/src/render/geometry/buffermanager.cpp
index 78c2c0082..5bd44f80f 100644
--- a/src/render/geometry/buffermanager.cpp
+++ b/src/render/geometry/buffermanager.cpp
@@ -66,18 +66,34 @@ QVector<Qt3DCore::QNodeId> BufferManager::dirtyBuffers()
}
// Called in QAspectThread::syncChanges
-void BufferManager::addBufferToRelease(Qt3DCore::QNodeId bufferId)
+void BufferManager::removeBufferReference(Qt3DCore::QNodeId bufferId)
{
QMutexLocker lock(&m_mutex);
- m_buffersToRelease.push_back(bufferId);
+ Q_ASSERT(m_bufferReferences.contains(bufferId) && m_bufferReferences[bufferId] > 0);
+ m_bufferReferences[bufferId]--;
+}
+
+// Called in QAspectThread
+void BufferManager::addBufferReference(Qt3DCore::QNodeId bufferId)
+{
+ QMutexLocker lock(&m_mutex);
+ m_bufferReferences[bufferId]++;
}
// Called in Render thread
QVector<Qt3DCore::QNodeId> BufferManager::takeBuffersToRelease()
{
QMutexLocker lock(&m_mutex);
- // Clears the m_buffersToRelease vector
- return std::move(m_buffersToRelease);
+ QVector<Qt3DCore::QNodeId> buffersToRelease;
+ QMutableHashIterator<Qt3DCore::QNodeId, int> it(m_bufferReferences);
+ while (it.hasNext()) {
+ it.next();
+ if (it.value() == 0) {
+ buffersToRelease.append(it.key());
+ it.remove();
+ }
+ }
+ return buffersToRelease;
}
} // namespace Render
diff --git a/src/render/geometry/buffermanager_p.h b/src/render/geometry/buffermanager_p.h
index 6862cd973..3eecb3664 100644
--- a/src/render/geometry/buffermanager_p.h
+++ b/src/render/geometry/buffermanager_p.h
@@ -76,13 +76,15 @@ public:
QVector<Qt3DCore::QNodeId> dirtyBuffers();
// Aspect Thread
- void addBufferToRelease(Qt3DCore::QNodeId bufferId);
+ void addBufferReference(Qt3DCore::QNodeId bufferId);
+ void removeBufferReference(Qt3DCore::QNodeId bufferId);
+
// Render Thread (no concurrent access)
QVector<Qt3DCore::QNodeId> takeBuffersToRelease();
private:
QVector<Qt3DCore::QNodeId> m_dirtyBuffers;
- QVector<Qt3DCore::QNodeId> m_buffersToRelease;
+ QHash<Qt3DCore::QNodeId, int> m_bufferReferences;
QMutex m_mutex;
};