summaryrefslogtreecommitdiff
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)
downloadqt3d-a9cd9784fb1a63ee5a0883a7a214d57dcaaaf026.tar.gz
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);
}