summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2018-07-19 08:54:13 +0200
committerPaul Lemire <paul.lemire@kdab.com>2018-07-20 19:46:48 +0000
commita9cd9784fb1a63ee5a0883a7a214d57dcaaaf026 (patch)
treedfa25711d0e1e142b948756c21ad132cbacaf18f
parentcdf92a8ba06c3df17a11c8931d540a4bf9229f61 (diff)
Fix crash when using Scene3D and updating data frequently
With Scene3D we can't assume that when we are rendering, resources haven't been deleted in the meantime. Add checks to verify a resource is not null before using it. Change-Id: I918ae77c2d3efc6efc53c6c5b5b9c03729978cba Task-number: QTBUG-69534 Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp26
1 files changed, 25 insertions, 1 deletions
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index 904527cd5..a970a0479 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -1170,7 +1170,16 @@ void Renderer::reloadDirtyShaders()
}
}
-// Render Thread
+// Render Thread (or QtQuick RenderThread when using Scene3D)
+// Scene3D: When using Scene3D rendering, we can't assume that when
+// updateGLResources is called, the resource handles points to still existing
+// objects. This is because Scene3D calls doRender independently of whether all
+// jobs have completed or not which in turn calls proceedToNextFrame under some
+// conditions. Such conditions are usually met on startup to avoid deadlocks.
+// proceedToNextFrame triggers the syncChanges calls for the next frame, which
+// may contain destruction changes targeting resources. When the above
+// happens, this can result in the dirtyResource vectors containing handles of
+// objects that may already have been destroyed
void Renderer::updateGLResources()
{
{
@@ -1178,6 +1187,11 @@ void Renderer::updateGLResources()
const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers);
for (const HBuffer &handle: dirtyBufferHandles) {
Buffer *buffer = m_nodesManager->bufferManager()->data(handle);
+
+ // Can be null when using Scene3D rendering
+ if (buffer == nullptr)
+ continue;
+
// Forces creation if it doesn't exit
// Also note the binding point doesn't really matter here, we just upload data
if (!m_submissionContext->hasGLBufferForBuffer(buffer))
@@ -1195,6 +1209,11 @@ void Renderer::updateGLResources()
ShaderManager *shaderManager = m_nodesManager->shaderManager();
for (const HShader &handle: dirtyShaderHandles) {
Shader *shader = shaderManager->data(handle);
+
+ // Can be null when using Scene3D rendering
+ if (shader == nullptr)
+ continue;
+
// Compile shader
m_submissionContext->loadShader(shader, shaderManager);
}
@@ -1206,6 +1225,11 @@ void Renderer::updateGLResources()
const QVector<HTexture> activeTextureHandles = std::move(m_dirtyTextures);
for (const HTexture &handle: activeTextureHandles) {
Texture *texture = m_nodesManager->textureManager()->data(handle);
+
+ // Can be null when using Scene3D rendering
+ if (texture == nullptr)
+ continue;
+
// Update texture properties
updateTexture(texture);
}