diff options
author | Tomi Korpipaa <tomi.korpipaa@qt.io> | 2023-04-20 06:58:27 +0300 |
---|---|---|
committer | Tomi Korpipaa <tomi.korpipaa@qt.io> | 2023-04-20 10:34:42 +0300 |
commit | 5720c0da7e4eae5b997923815bbe7ebdfa00a079 (patch) | |
tree | 815a7d1e6f0401f33c208b9cd2178bc99755112d | |
parent | ff3d6efeb62575a5af503ee19db462cc6ff980e2 (diff) |
Fix crash when a custom material / effect shader variable changes
We ended up deleting valid commands in cases where a shader variable
changed without the custom material or effect being deleted. Just redo
the to-be-deleted command list in updateSpatialNode instead of deleting
it.
Fixes: QTBUG-112969
Change-Id: Iec9bc584711325052f27353587632c4399b1fe4d
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/quick3d/qquick3dcustommaterial.cpp | 24 | ||||
-rw-r--r-- | src/quick3d/qquick3deffect.cpp | 24 |
2 files changed, 28 insertions, 20 deletions
diff --git a/src/quick3d/qquick3dcustommaterial.cpp b/src/quick3d/qquick3dcustommaterial.cpp index a2b1d390..ed5ac987 100644 --- a/src/quick3d/qquick3dcustommaterial.cpp +++ b/src/quick3d/qquick3dcustommaterial.cpp @@ -514,18 +514,22 @@ QSSGRenderGraphObject *QQuick3DCustomMaterial::updateSpatialNode(QSSGRenderGraph // We need to mark the commands that we allocated since they will need to be deallocted when the customMaterial is deleted. // We achieve this by filtering on the command type. - qDeleteAll(customMaterial->commandsToDelete); + // Just redo the list without deleting it, or we end up calling already deleted commands in + // render if a shader variable changes. customMaterial->commandsToDelete.clear(); for (auto command : customMaterial->commands) { - if (command->m_type != dynamic::CommandType::AllocateBuffer && - command->m_type != dynamic::CommandType::ApplyBufferValue && - command->m_type != dynamic::CommandType::ApplyBlitFramebuffer && - command->m_type != dynamic::CommandType::ApplyBlending && - command->m_type != dynamic::CommandType::ApplyRenderState && - command->m_type != dynamic::CommandType::ApplyCullMode && - command->m_type != dynamic::CommandType::ApplyDepthValue && - command->m_type != dynamic::CommandType::ApplyValue) - customMaterial->commandsToDelete.insert(command); + if (command->m_type > dynamic::CommandType::Unknown && + command->m_type < dynamic::CommandType::ApplyCullMode && + command->m_type != dynamic::CommandType::AllocateBuffer && + command->m_type != dynamic::CommandType::ApplyBufferValue && + command->m_type != dynamic::CommandType::ApplyBlitFramebuffer && + command->m_type != dynamic::CommandType::ApplyBlending && + command->m_type != dynamic::CommandType::ApplyRenderState && + command->m_type != dynamic::CommandType::ApplyCullMode && + command->m_type != dynamic::CommandType::ApplyDepthValue && + command->m_type != dynamic::CommandType::ApplyValue) { + customMaterial->commandsToDelete.insert(command); + } } QQuick3DMaterial::updateSpatialNode(customMaterial); diff --git a/src/quick3d/qquick3deffect.cpp b/src/quick3d/qquick3deffect.cpp index 7b2681a3..af2208b0 100644 --- a/src/quick3d/qquick3deffect.cpp +++ b/src/quick3d/qquick3deffect.cpp @@ -389,18 +389,22 @@ QSSGRenderGraphObject *QQuick3DEffect::updateSpatialNode(QSSGRenderGraphObject * // We need to mark the commands that we allocated since they will need to be deallocted when the customMaterial is deleted. // We achieve this by filtering on the command type. - qDeleteAll(effectNode->commandsToDelete); + // Just redo the list without deleting it, or we end up calling already deleted commands in + // render if a shader variable changes effectNode->commandsToDelete.clear(); for (auto command : effectNode->commands) { - if (command->m_type != dynamic::CommandType::AllocateBuffer && - command->m_type != dynamic::CommandType::ApplyBufferValue && - command->m_type != dynamic::CommandType::ApplyBlitFramebuffer && - command->m_type != dynamic::CommandType::ApplyBlending && - command->m_type != dynamic::CommandType::ApplyRenderState && - command->m_type != dynamic::CommandType::ApplyCullMode && - command->m_type != dynamic::CommandType::ApplyDepthValue && - command->m_type != dynamic::CommandType::ApplyValue) - effectNode->commandsToDelete.insert(command); + if (command->m_type > dynamic::CommandType::Unknown && + command->m_type < dynamic::CommandType::ApplyCullMode && + command->m_type != dynamic::CommandType::AllocateBuffer && + command->m_type != dynamic::CommandType::ApplyBufferValue && + command->m_type != dynamic::CommandType::ApplyBlitFramebuffer && + command->m_type != dynamic::CommandType::ApplyBlending && + command->m_type != dynamic::CommandType::ApplyRenderState && + command->m_type != dynamic::CommandType::ApplyCullMode && + command->m_type != dynamic::CommandType::ApplyDepthValue && + command->m_type != dynamic::CommandType::ApplyValue) { + effectNode->commandsToDelete.insert(command); + } } if (m_dirtyAttributes & Dirty::PropertyDirty) { |