diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2018-07-19 08:54:13 +0200 |
---|---|---|
committer | Paul Lemire <paul.lemire@kdab.com> | 2018-07-20 19:46:48 +0000 |
commit | a9cd9784fb1a63ee5a0883a7a214d57dcaaaf026 (patch) | |
tree | dfa25711d0e1e142b948756c21ad132cbacaf18f | |
parent | cdf92a8ba06c3df17a11c8931d540a4bf9229f61 (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.cpp | 26 |
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); } |