diff options
author | Miikka Heikkinen <miikka.heikkinen@theqtcompany.com> | 2015-06-29 11:55:49 +0300 |
---|---|---|
committer | Miikka Heikkinen <miikka.heikkinen@theqtcompany.com> | 2015-06-29 10:59:37 +0000 |
commit | 44ed21d13964fc6aec0a13d0b82ccbbabd9aec86 (patch) | |
tree | f849790e868d489ab5bf5401fd07902acb2ce9fa | |
parent | 6526fd259530978e88b3365d7e95b57f60833799 (diff) |
Make command queue size semi-dynamic
Command queue will now allocate more space if it runs out up until
specified maximum size. This makes it to both consume less memory in
most cases and behave better on background rendering cases that
exceeded the old maximum size.
Change-Id: I74d20b9bf7e2f028dd946b9348f0235b0e959682
Reviewed-by: Tomi Korpipää <tomi.korpipaa@theqtcompany.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com>
-rw-r--r-- | src/imports/qtcanvas3d/canvasrenderer.cpp | 11 | ||||
-rw-r--r-- | src/imports/qtcanvas3d/glcommandqueue.cpp | 47 | ||||
-rw-r--r-- | src/imports/qtcanvas3d/glcommandqueue_p.h | 7 |
3 files changed, 41 insertions, 24 deletions
diff --git a/src/imports/qtcanvas3d/canvasrenderer.cpp b/src/imports/qtcanvas3d/canvasrenderer.cpp index a9e0420..377faf6 100644 --- a/src/imports/qtcanvas3d/canvasrenderer.cpp +++ b/src/imports/qtcanvas3d/canvasrenderer.cpp @@ -48,7 +48,8 @@ QT_BEGIN_NAMESPACE QT_CANVAS3D_BEGIN_NAMESPACE -const int commandQueueSize = 10000; +const int initialQueueSize = 256; +const int maxQueueSize = 1000000; /*! * \internal @@ -73,7 +74,7 @@ CanvasRenderer::CanvasRenderer(QObject *parent): m_displayFbo(0), m_recreateFbos(false), m_offscreenSurface(0), - m_commandQueue(0), // command queue will be reset when context is created. + m_commandQueue(0, maxQueueSize), // command queue size will be reset when context is created. m_executeQueue(0), m_executeQueueCount(0), m_executeStartIndex(0), @@ -179,8 +180,8 @@ void CanvasRenderer::init(QQuickWindow *window, const CanvasContextAttributes &c } #endif - m_commandQueue.resetQueue(commandQueueSize); - m_executeQueue.resize(commandQueueSize); + m_commandQueue.resetQueue(initialQueueSize); + m_executeQueue.resize(initialQueueSize); m_executeQueueCount = 0; m_executeStartIndex = 0; m_executeEndIndex = 0; @@ -739,6 +740,8 @@ void CanvasRenderer::transferCommands() { if (m_glContext) { const int count = m_commandQueue.queuedCount(); + if (count > m_executeQueue.size()) + m_executeQueue.resize(count); if (m_renderTarget == Canvas::RenderTargetOffscreenBuffer) { m_executeQueueCount = count; m_commandQueue.transferCommands(m_executeQueue); diff --git a/src/imports/qtcanvas3d/glcommandqueue.cpp b/src/imports/qtcanvas3d/glcommandqueue.cpp index cef8150..5d18c82 100644 --- a/src/imports/qtcanvas3d/glcommandqueue.cpp +++ b/src/imports/qtcanvas3d/glcommandqueue.cpp @@ -55,16 +55,17 @@ QT_CANVAS3D_BEGIN_NAMESPACE * The command data is copied for execution when GUI thread is blocked, so no extra synchronization * is needed for that. */ -CanvasGlCommandQueue::CanvasGlCommandQueue(int size, QObject *parent) : +CanvasGlCommandQueue::CanvasGlCommandQueue(int initialSize, int maxSize, QObject *parent) : QObject(parent), - m_maxSize(0), + m_maxSize(maxSize), + m_size(0), m_queuedCount(0), m_nextResourceId(1), m_resourceIdOverflow(false), m_clearMask(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT) { - resetQueue(size); + resetQueue(initialSize); } CanvasGlCommandQueue::~CanvasGlCommandQueue() @@ -79,21 +80,31 @@ CanvasGlCommandQueue::~CanvasGlCommandQueue() * \internal * * Queues a new command \a id to the next available slot and returns a reference to that command, - * so the caller can give it additional parameters. + * so the caller can give it additional parameters. If the queue is full, we simply reallocate some + * more space up to the max size. */ GlCommand &CanvasGlCommandQueue::queueCommand(CanvasGlCommandQueue::GlCommandId id) { - // If queue is full, we need to clear it first - if (m_queuedCount == m_maxSize) { - emit queueFull(); - // queueFull handling should reset the queue, but in case renderer thread is not available - // to handle the commands for some reason, let's reset the count. In that case the entire - // queue is lost, so results may not be pretty, but nothing much can be done about it. - // Let's at least make sure we don't leak any memory. - if (m_queuedCount) { - deleteUntransferedCommandData(); - m_queuedCount = 0; - clearQuickItemAsTextureList(); + // Increase queue size if we run out of space. Note that this should only happen on the first + // frame on most applications, as we never decrease the allocated size. + if (m_queuedCount == m_size) { + // If queue is full and at max size, we need to synchronously execute all commands + if (m_queuedCount == m_maxSize) { + emit queueFull(); + // queueFull handling should reset the queue, but in case renderer thread is not available + // to handle the commands for some reason, let's reset the count. In that case the entire + // queue is lost, so results may not be pretty, but nothing much can be done about it. + // Let's at least make sure we don't leak any memory. + if (m_queuedCount) { + deleteUntransferedCommandData(); + m_queuedCount = 0; + clearQuickItemAsTextureList(); + } + } else { + m_size += m_size / 2; + if (m_size > m_maxSize) + m_size = m_maxSize; + m_queue.resize(m_size); } } @@ -212,10 +223,12 @@ void CanvasGlCommandQueue::resetQueue(int size) clearQuickItemAsTextureList(); m_queuedCount = 0; - m_maxSize = size; + m_size = size; + if (m_size > m_maxSize) + m_size = m_maxSize; m_queue.clear(); - m_queue.resize(m_maxSize); + m_queue.resize(m_size); m_resourceIdOverflow = false; m_nextResourceId = 1; diff --git a/src/imports/qtcanvas3d/glcommandqueue_p.h b/src/imports/qtcanvas3d/glcommandqueue_p.h index 658df38..b5e8123 100644 --- a/src/imports/qtcanvas3d/glcommandqueue_p.h +++ b/src/imports/qtcanvas3d/glcommandqueue_p.h @@ -227,7 +227,7 @@ public: }; - CanvasGlCommandQueue(int size = 10000, QObject *parent = 0); + CanvasGlCommandQueue(int initialSize, int maxSize, QObject *parent = 0); ~CanvasGlCommandQueue(); int queuedCount() const { return m_queuedCount; } @@ -294,6 +294,7 @@ signals: private: QVector<GlCommand> m_queue; int m_maxSize; + int m_size; int m_queuedCount; QMap<GLint, GlResource> m_resourceIdMap; @@ -351,8 +352,6 @@ public: data = 0; } - CanvasGlCommandQueue::GlCommandId id; - // Optional extra data such as buffer contents for commands that need it. The data is deleted // after the command is handled. Not owned by command itself. // Queue owns the data before it is transferred to execution, after which the CanvasRenderer @@ -360,6 +359,8 @@ public: // whoever owns the command object. QByteArray *data; + CanvasGlCommandQueue::GlCommandId id; + GLint i1; GLint i2; GLint i3; |