diff options
author | Gunnar Sletta <gunnar.sletta@digia.com> | 2013-11-06 10:06:27 +0100 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-11-09 22:46:47 +0100 |
commit | afee694ce5d65518e5908b97e9a691c03fe0a844 (patch) | |
tree | be6e714703b799791cdacbea4b315471ab9b6a03 /src | |
parent | 7b75c3e63e7842c2667f58d43d44e21ff57ac0c8 (diff) |
Avoid using huge floating point values in the renderer.
We pretransform vertices relative to their batch root and upload these
using single-precision floats. If the offsets are huge then the
floating point numbers start to get unstable and we get rendering
artifacts as a result. This typically happens for lists/tables with
huge models.
Task-number: QTBUG-34312
Change-Id: I2516f2b4fa93f44a1288659d05458fb1af0df943
Reviewed-by: Laszlo Agocs <laszlo.agocs@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp | 24 | ||||
-rw-r--r-- | src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h | 13 |
2 files changed, 32 insertions, 5 deletions
diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp index bb98682b20..3ea4b2ee1e 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer.cpp @@ -562,6 +562,8 @@ void Element::computeBounds() bounds.br.x = FLT_MAX; if (!qIsFinite(bounds.br.y)) bounds.br.y = FLT_MAX; + + boundsOutsideFloatRange = bounds.isOutsideFloatRange(); } RenderNodeElement::~RenderNodeElement() @@ -662,12 +664,26 @@ bool Batch::isTranslateOnlyToRoot() const { /* * Iterates through all the nodes in the batch and returns true if the - * nodes are all "2D safe" meaning that they can be merged and that - * the value in the z coordinate is of no consequence. + * nodes are all safe to batch. There are two separate criteria: + * + * - The matrix is such that the z component of the result is of no + * consequence. + * + * - The bounds are inside the stable floating point range. This applies + * to desktop only where we in this case can trigger a fallback to + * unmerged in which case we pass the geometry straight through and + * just apply the matrix. + * + * NOTE: This also means a slight performance impact for geometries which + * are defined to be outside the stable floating point range and still + * use single precision float, but given that this implicitly fixes + * huge lists and tables, it is worth it. */ -bool Batch::allMatricesAre2DSafe() const { +bool Batch::isSafeToBatch() const { Element *e = first; while (e) { + if (e->boundsOutsideFloatRange) + return false; if (!QMatrix4x4_Accessor::is2DSafe(*e->node->matrix())) return false; e = e->nextInBatch; @@ -1637,7 +1653,7 @@ void Renderer::uploadBatch(Batch *b) && (((gn->activeMaterial()->flags() & QSGMaterial::RequiresDeterminant) == 0) || (((gn->activeMaterial()->flags() & QSGMaterial_RequiresFullMatrixBit) == 0) && b->isTranslateOnlyToRoot()) ) - && b->allMatricesAre2DSafe(); + && b->isSafeToBatch(); b->merged = canMerge; diff --git a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h index 23985729ef..6d95f83d7a 100644 --- a/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h +++ b/src/quick/scenegraph/coreapi/qsgbatchrenderer_p.h @@ -53,6 +53,8 @@ QT_BEGIN_NAMESPACE namespace QSGBatchRenderer { +#define QSG_RENDERER_COORD_LIMIT 1000000.0f + struct Vec; struct Rect; struct Buffer; @@ -136,6 +138,13 @@ struct Rect { bool yOverlap = r.tl.y < br.y && r.br.y > tl.y; return xOverlap && yOverlap; } + + bool isOutsideFloatRange() const { + return tl.x < -QSG_RENDERER_COORD_LIMIT + || tl.y < -QSG_RENDERER_COORD_LIMIT + || br.x > QSG_RENDERER_COORD_LIMIT + || br.y > QSG_RENDERER_COORD_LIMIT; + } }; inline QDebug operator << (QDebug d, const Rect &r) { @@ -158,6 +167,7 @@ struct Element { , root(0) , order(0) , boundsComputed(false) + , boundsOutsideFloatRange(false) , translateOnlyToRoot(false) , removed(false) , orphaned(false) @@ -181,6 +191,7 @@ struct Element { int order; uint boundsComputed : 1; + uint boundsOutsideFloatRange : 1; uint translateOnlyToRoot : 1; uint removed : 1; uint orphaned : 1; @@ -242,7 +253,7 @@ struct Batch void cleanupRemovedElements(); bool isTranslateOnlyToRoot() const; - bool allMatricesAre2DSafe() const; + bool isSafeToBatch() const; // pseudo-constructor... void init() { |