QmlDesigner: Work around the issue in QtQuick3D 6.4 geometry caching

QQuick3DGeometry::updateSpatialNode can create QSSGRenderGeometry
object with exact same address as a previously created and subsequently
deleted QSSGRenderGeometry object (i.e. the memory location is reused).
If the previous node was not used for the exact same logical geometry,
then you get these artifacts, as QSSGBufferManager uses
QSSGRenderGeometry object pointers in QSSGBufferManager::loadRenderMesh
function to determine if it needs to reload the geometry and what
geometry gets used for each model. The cache still contains data for
the deleted node, which is then matched for the new node with same
address.

This workaround ensures that none of our grid geometries will have the
same generation id and thus will never get improperly matched in
QSSGBufferManager cache.

Task-number: QDS-8516
Change-Id: I017a4ae4a59eef2bb26ade5abf13e8f74f57c4af
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
This commit is contained in:
Miikka Heikkinen
2022-12-08 12:35:57 +02:00
parent e70f909bcf
commit 636c9524f9
2 changed files with 35 additions and 0 deletions

View File

@@ -5,6 +5,10 @@
#include "gridgeometry.h" #include "gridgeometry.h"
#if QT_VERSION_MAJOR == 6 && QT_VERSION_MINOR == 4
#include <private/qssgrendergeometry_p.h>
#endif
namespace QmlDesigner { namespace QmlDesigner {
namespace Internal { namespace Internal {
@@ -82,6 +86,34 @@ void GridGeometry::doUpdateGeometry()
QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0)); QVector3D(vertexPtr[lastIndex][0], vertexPtr[lastIndex][1], 0.0));
} }
#if QT_VERSION_MAJOR == 6 && QT_VERSION_MINOR == 4
QSSGRenderGraphObject *GridGeometry::updateSpatialNode(QSSGRenderGraphObject *node)
{
if (!node) {
markAllDirty();
auto geometryNode = new QSSGRenderGeometry();
node = geometryNode;
emit geometryNodeDirty();
// This is a work around for the issue of incorrect geometry objects getting matched for
// cached mesh data in QSSGBufferManager::loadRenderMesh in QtQuick3D in 6.4 (see QDS-8516).
// Each setting of stride value increments the generation id of the geometry node.
// By incrementing generation id by different amounts for each grid geometry node we have,
// we can ensure QSSGBufferManager cache never matches wrong mesh data.
// The cache should be cleared of old objects after they are unused for one frame,
// and we use 4 grid objects in total, so max of 8 different generation ids should ensure no
// invalid cache matches.
static int dirtyCount = 0;
if (++dirtyCount > 8)
dirtyCount = 0;
for (int i = 0; i < dirtyCount; ++i)
geometryNode->setStride(stride());
}
return QQuick3DGeometry::updateSpatialNode(node);
}
#endif
void GridGeometry::fillVertexData(QByteArray &vertexData) void GridGeometry::fillVertexData(QByteArray &vertexData)
{ {
const int numSubdivs = 1; // number of subdivision lines (i.e. lines between main grid lines) const int numSubdivs = 1; // number of subdivision lines (i.e. lines between main grid lines)

View File

@@ -39,6 +39,9 @@ signals:
protected: protected:
void doUpdateGeometry() override; void doUpdateGeometry() override;
#if QT_VERSION_MAJOR == 6 && QT_VERSION_MINOR == 4
QSSGRenderGraphObject *updateSpatialNode(QSSGRenderGraphObject *node) override;
#endif
private: private:
void fillVertexData(QByteArray &vertexData); void fillVertexData(QByteArray &vertexData);