aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTomi Korpipaa <tomi.korpipaa@qt.io>2023-04-20 06:58:27 +0300
committerTomi Korpipaa <tomi.korpipaa@qt.io>2023-04-20 10:34:42 +0300
commit5720c0da7e4eae5b997923815bbe7ebdfa00a079 (patch)
tree815a7d1e6f0401f33c208b9cd2178bc99755112d
parentff3d6efeb62575a5af503ee19db462cc6ff980e2 (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.cpp24
-rw-r--r--src/quick3d/qquick3deffect.cpp24
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) {