summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2014-06-25 16:08:30 +0200
committerSean Harmer <sean.harmer@kdab.com>2014-07-03 00:10:31 +0200
commitc7dcb02e6a1c8fe4cc4a24cbe2c1b6d2663ee3d9 (patch)
treef118fa5440e5a384b89c45a143a4fa3eb451e2bf /src
parent6f7a5c92e2a989eb7207f4d2e5a66fb431b9f538 (diff)
Rendering using QFrameAllocator
Renderer contains a QThreadStorage object containing a vector of QFrameAllocator. Each Renderview Jobs calls the Renderer to retrieve the QFrameAllocator for their thread and their frame index (between 0 and the maximum number of cached frames). If the QThreadStorage hasn't been initialized, it is initialized, otherwise the QFrameAllocator is returned directly. The QFrameAllocator is automatically cleared if the previous call wasn't for the same frame index. QUniformValues and RenderViews have been updated to used QFrameAllocator to allocate objects instead of using new. RenderQueue has been slightly modified. It is now possible to retrieve the RenderQueue to render without popping it out of the QCircularBuffer of RenderQueues. A call to popFrameQueue does that. This is needed to be sure that we won't be rendering a RenderQueue that could have been cleared because the backend is rebuilding a newer frame. This forces the Renderer to render the whole frame before allowing the Jobs to build other frames if there are more than the maximum amount of cached frames. Change-Id: Ie7718e201e2f6b420903092d1706277e9786916e Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src')
-rw-r--r--src/render/backend/jobs/renderviewjob.cpp24
-rw-r--r--src/render/backend/jobs/renderviewjob.h3
-rw-r--r--src/render/backend/quniformvalue.cpp91
-rw-r--r--src/render/backend/quniformvalue.h22
-rw-r--r--src/render/backend/renderer.cpp54
-rw-r--r--src/render/backend/renderer.h13
-rw-r--r--src/render/backend/renderqueues.cpp17
-rw-r--r--src/render/backend/renderqueues.h3
-rw-r--r--src/render/backend/renderview.cpp114
-rw-r--r--src/render/backend/renderview.h36
-rw-r--r--src/render/renderlogging.cpp1
-rw-r--r--src/render/renderlogging.h1
12 files changed, 288 insertions, 91 deletions
diff --git a/src/render/backend/jobs/renderviewjob.cpp b/src/render/backend/jobs/renderviewjob.cpp
index cbc9b6f55..4c7804de6 100644
--- a/src/render/backend/jobs/renderviewjob.cpp
+++ b/src/render/backend/jobs/renderviewjob.cpp
@@ -53,26 +53,18 @@ namespace Render {
void RenderViewJob::run()
{
- qCDebug(Jobs) << Q_FUNC_INFO << m_index;
-
- if (!m_tlsAllocators.hasLocalData()) {
- QFrameAllocatorQueue *allocatorQueue = new QFrameAllocatorQueue();
- m_tlsAllocators.setLocalData(allocatorQueue);
-
- // RenderView has a sizeof 72
- // RenderCommand has a sizeof 128
- // QMatrix4x4 has a sizeof 68
- // May need to fine tune parameters passed to QFrameAllocator for best performances
- for (int i = 0; i < m_renderer->cachedFramesCount(); i++)
- allocatorQueue->append(new QFrameAllocator(128, 16, 128));
- }
+ qCDebug(Jobs) << Q_FUNC_INFO << m_index << " frame " << m_frameIndex;
// Create a RenderView object
- // The RenderView should be created from a QFrameAllocator stored in the current Thread local storage
- // Store in an array or circular buffer that we can access using m_frameIndex.
- RenderView *renderView = new RenderView;
+ // The RenderView are created from a QFrameAllocator stored in the current Thread local storage
+
+ QFrameAllocator *currentFrameAllocator = m_renderer->currentFrameAllocator(m_frameIndex);
+ RenderView *renderView = currentFrameAllocator->allocate<RenderView>();
+ // RenderView should allocate heap resources using only the currentFrameAllocator
+ renderView->setAllocator(currentFrameAllocator);
renderView->setRenderer(m_renderer);
+ renderView->setFrameIndex(m_frameIndex);
// Populate its configuration from the framegraph
// using the root->leaf set of nodes
renderView->setConfigFromFrameGraphLeafNode(m_fgLeaf);
diff --git a/src/render/backend/jobs/renderviewjob.h b/src/render/backend/jobs/renderviewjob.h
index ea84ee701..952b408a5 100644
--- a/src/render/backend/jobs/renderviewjob.h
+++ b/src/render/backend/jobs/renderviewjob.h
@@ -50,13 +50,11 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
-
namespace Render {
class Renderer;
class FrameGraphNode;
-typedef QVector<QFrameAllocator *> QFrameAllocatorQueue;
class RenderViewJob : public QJob
{
@@ -93,7 +91,6 @@ private:
// We are currently processing that RenderView for.
// This is useful to retrieve data index by frame index
int m_frameIndex;
- QThreadStorage<QFrameAllocatorQueue *> m_tlsAllocators;
};
typedef QSharedPointer<RenderViewJob> RenderViewJobPtr;
diff --git a/src/render/backend/quniformvalue.cpp b/src/render/backend/quniformvalue.cpp
index 232a1b54e..1deba661a 100644
--- a/src/render/backend/quniformvalue.cpp
+++ b/src/render/backend/quniformvalue.cpp
@@ -44,6 +44,8 @@
#include "qgraphicscontext.h"
#include "rendertexture.h"
+#include <Qt3DCore/qframeallocator.h>
+
#include <QOpenGLShaderProgram>
#include <QDebug>
#include <QColor>
@@ -62,24 +64,81 @@ QUniformValue::QUniformValue() :
{
}
-QUniformValue *QUniformValue::fromVariant(const QVariant &v)
+QUniformValue *QUniformValue::fromVariant(const QVariant &v, QFrameAllocator *allocator)
{
switch (v.type()) {
- case QVariant::Int: return new SpecifiedUniform<int>(v.toInt());
- case QVariant::UInt: return new SpecifiedUniform<uint>(v.toUInt());
- case QVariant::Double: return new SpecifiedUniform<float>(v.toFloat());
- case QVariant::Vector2D: return new SpecifiedUniform<QVector2D>(v.value<QVector2D>());
- case QVariant::Vector3D: return new SpecifiedUniform<QVector3D>(v.value<QVector3D>());
- case QVariant::Vector4D: return new SpecifiedUniform<QVector4D>(v.value<QVector4D>());
- case QVariant::Matrix4x4: return new SpecifiedUniform<QMatrix4x4>(v.value<QMatrix4x4>());
- case QVariant::Point: return new SpecifiedUniform<QPoint>(v.value<QPoint>());
- case QVariant::PointF: return new SpecifiedUniform<QPointF>(v.value<QPointF>());
- case QVariant::Size: return new SpecifiedUniform<QSize>(v.value<QSize>());
- case QVariant::SizeF: return new SpecifiedUniform<QSizeF>(v.value<QSizeF>());
- case QVariant::Transform: return new SpecifiedUniform<QTransform>(v.value<QTransform>());
- case QVariant::Color: return new SpecifiedUniform<QColor>(v.value<QColor>());
- case QVariant::Quaternion: return new SpecifiedUniform<QVector4D>(v.value<QVector4D>());
- default: return new QUniformValue();
+ case QVariant::Int: {
+ SpecifiedUniform<int> *t = allocator->allocate<SpecifiedUniform<int> >();
+ t->setValue(v.toInt());
+ return t;
+ }
+ case QVariant::UInt: {
+ SpecifiedUniform<uint> *t = allocator->allocate<SpecifiedUniform<uint> >();
+ t->setValue(v.toUInt());
+ return t;
+ }
+ case QVariant::Double: {
+ SpecifiedUniform<float> *t = allocator->allocate<SpecifiedUniform<float> >();
+ t->setValue(v.toFloat());
+ return t;
+ }
+ case QVariant::Vector2D: {
+ SpecifiedUniform<QVector2D> *t = allocator->allocate<SpecifiedUniform<QVector2D> >();
+ t->setValue(v.value<QVector2D>());
+ return t;
+ }
+ case QVariant::Vector3D: {
+ SpecifiedUniform<QVector3D> *t = allocator->allocate<SpecifiedUniform<QVector3D> >();
+ t->setValue(v.value<QVector3D>());
+ return t;
+ }
+ case QVariant::Vector4D: {
+ SpecifiedUniform<QVector4D> *t = allocator->allocate<SpecifiedUniform<QVector4D> >();
+ t->setValue(v.value<QVector4D>());
+ return t;
+ }
+ case QVariant::Matrix4x4: {
+ SpecifiedUniform<QMatrix4x4> *t = allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(v.value<QMatrix4x4>());
+ return t;
+ }
+ case QVariant::Point: {
+ SpecifiedUniform<QPoint> *t = allocator->allocate<SpecifiedUniform<QPoint> >();
+ t->setValue(v.value<QPoint>());
+ return t;
+ }
+ case QVariant::PointF: {
+ SpecifiedUniform<QPointF> *t = allocator->allocate<SpecifiedUniform<QPointF> >();
+ t->setValue(v.value<QPointF>());
+ return t;
+ }
+ case QVariant::Size: {
+ SpecifiedUniform<QSize> *t = allocator->allocate<SpecifiedUniform<QSize> >();
+ t->setValue(v.value<QSize>());
+ return t;
+ }
+ case QVariant::SizeF: {
+ SpecifiedUniform<QSizeF> *t = allocator->allocate<SpecifiedUniform<QSizeF> >();
+ t->setValue(v.value<QSizeF>());
+ return t;
+ }
+ case QVariant::Transform: {
+ SpecifiedUniform<QTransform> *t = allocator->allocate<SpecifiedUniform<QTransform> >();
+ t->setValue(v.value<QTransform>());
+ return t;
+ }
+ case QVariant::Color: {
+ SpecifiedUniform<QColor> *t = allocator->allocate<SpecifiedUniform<QColor> >();
+ t->setValue(v.value<QColor>());
+ return t;
+ }
+ case QVariant::Quaternion: {
+ SpecifiedUniform<QVector4D> *t = allocator->allocate<SpecifiedUniform<QVector4D> >();
+ t->setValue(v.value<QVector4D>());
+ return t;
+ }
+ default:
+ return allocator->allocate<QUniformValue>();
}
}
diff --git a/src/render/backend/quniformvalue.h b/src/render/backend/quniformvalue.h
index 82df74dc0..daf18f098 100644
--- a/src/render/backend/quniformvalue.h
+++ b/src/render/backend/quniformvalue.h
@@ -57,6 +57,9 @@ QT_BEGIN_NAMESPACE
class QOpenGLShaderProgram;
namespace Qt3D {
+
+class QFrameAllocator;
+
namespace Render {
class QGraphicsContext;
@@ -81,7 +84,7 @@ public:
QUniformValue();
virtual ~QUniformValue() {}
- static QUniformValue *fromVariant(const QVariant &v);
+ static QUniformValue *fromVariant(const QVariant &v, QFrameAllocator *allocator);
virtual bool operator ==(const QUniformValue &other);
bool operator !=(const QUniformValue &other);
@@ -113,13 +116,14 @@ template <typename T>
class SpecifiedUniform : public QUniformValue
{
public :
- explicit SpecifiedUniform(const T &value)
+ SpecifiedUniform()
: QUniformValue()
- , m_value(value)
{
m_type = Custom;
}
+ void setValue(const T &value) { m_value = value; }
+
bool operator ==(const QUniformValue &other) Q_DECL_OVERRIDE
{
Q_UNUSED(other);
@@ -145,15 +149,19 @@ private :
class TextureUniform : public QUniformValue
{
public :
- explicit TextureUniform(const QUuid &textureId)
+ TextureUniform()
: QUniformValue()
- , m_textureId(textureId)
, m_textureUnit(-1)
{
m_type = Texture;
}
- const QUuid textureId() const { return m_textureId; }
+ void setTextureId(const QUuid &textureId)
+ {
+ m_textureId = textureId;
+ }
+
+ QUuid textureId() const { return m_textureId; }
bool operator ==(const QUniformValue &other) Q_DECL_OVERRIDE
{
@@ -181,7 +189,7 @@ public :
}
private:
- const QUuid m_textureId;
+ QUuid m_textureId;
int m_textureUnit;
};
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 3e99e6000..004548070 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -124,12 +124,12 @@ Renderer::Renderer(int cachedFrames)
, m_renderPassManager(new RenderPassManager())
, m_textureManager(new TextureManager())
, m_textureDataManager(new TextureDataManager())
- , m_renderQueues(new RenderQueues(cachedFrames))
+ , m_renderQueues(new RenderQueues(cachedFrames - 1))
, m_frameCount(0)
, m_cachedFramesCount(cachedFrames)
{
m_graphicContextInitialized.fetchAndStoreOrdered(0);
- m_currentPreprocessingFrameIndex.fetchAndStoreOrdered(0);
+ m_currentPreprocessingFrameIndex = 0;
m_textureProvider = new RenderTextureProvider;
buildDefaultTechnique();
@@ -137,6 +137,7 @@ Renderer::Renderer(int cachedFrames)
QLoggingCategory::setFilterRules(QString::fromUtf8( // multiline QStringLiteral doesn't compile on Windows...
"Qt3D.Render.*.debug=false\n"
+ // "Qt3D.Render.Memory.debug=true\n"
// "Qt3D.Render.Rendering.debug=true\n"
// "Qt3D.Render.RenderNodes.debug=true\n"
// "Qt3D.Render.Frontend.debug=true\n"
@@ -249,6 +250,33 @@ void Renderer::initialize()
}
+QFrameAllocator *Renderer::currentFrameAllocator(int frameIndex)
+{
+ // frameIndex between 0 and m_cachedFramesCount
+ if (!m_tlsAllocators.hasLocalData()) {
+ qCDebug(Render::Backend) << Q_FUNC_INFO << "Initializing local data for Thread " << QThread::currentThread();
+ // RenderView has a sizeof 72
+ // RenderCommand has a sizeof 128
+ // QMatrix4x4 has a sizeof 68
+ // May need to fine tune parameters passed to QFrameAllocator for best performances
+ // We need to allocate one more buffer than we have frames to handle the case where we're computing frame 5
+ // While old frame 5 is being rendered
+ QFrameAllocatorQueue *allocatorQueue = new QFrameAllocatorQueue();
+ for (int i = 0; i < m_cachedFramesCount; i++)
+ allocatorQueue->append(new QFrameAllocator(128, 16, 128));
+ m_tlsAllocators.setLocalData(QPair<int, QFrameAllocatorQueue *>(0, allocatorQueue));
+ }
+ QPair<int, QFrameAllocatorQueue *> &data = m_tlsAllocators.localData();
+ // Check if index is the same as the current frame
+ // Otherwise we have to clear the QFrameAllocator at frameIndex
+ if (data.first != frameIndex) {
+ qCDebug(Render::Memory) << Q_FUNC_INFO << "clearing " << frameIndex << " previous" << data.first;
+ data.first = frameIndex;
+ data.second->at(frameIndex)->clear();
+ }
+ return data.second->at(frameIndex);
+}
+
void Renderer::setFrameGraphRoot(Render::FrameGraphNode *fgRoot)
{
qCDebug(Backend) << Q_FUNC_INFO;
@@ -333,14 +361,15 @@ void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder
// qDebug() << Q_FUNC_INFO << QThread::currentThread();
m_renderQueues->queueRenderView(renderView, submitOrder);
if (m_renderQueues->isFrameQueueComplete()) {
- m_renderQueues->pushFrameQueue();
// We can increment the currentProcessingFrameIndex here
// That index will then be used by RenderViewJobs to know which QFrameAllocator to use
// Increasing the frameIndex at that point is safe because :
// - This method is called by the last RenderViewJobs in ThreadWeaver
// - A new call to generate new RenderViewJobs cannot happen before all RenderViewJobs have finished executing aka locking the AspectThread
// - The Renderer thread doesn't modify the currentPreprocessingFrameIndex value
- m_currentPreprocessingFrameIndex.fetchAndStoreOrdered((m_currentPreprocessingFrameIndex.loadAcquire() + 1) % m_cachedFramesCount);
+ m_currentPreprocessingFrameIndex = (m_currentPreprocessingFrameIndex + 1) % m_cachedFramesCount;
+ m_renderQueues->pushFrameQueue();
+ qCDebug(Memory) << Q_FUNC_INFO << "Next frame index " << m_currentPreprocessingFrameIndex;
m_submitRenderViewsCondition.wakeOne();
}
}
@@ -374,28 +403,27 @@ void Renderer::submitRenderViews()
timer.start();
while (m_renderQueues->queuedFrames() > 0)
{
- QVector<Render::RenderView *> renderViews = m_renderQueues->popFrameQueue();
+ QVector<Render::RenderView *> renderViews = m_renderQueues->nextFrameQueue();
int renderViewsCount = renderViews.size();
quint64 frameElapsed = queueElapsed;
m_graphicsContext->beginDrawing();
-
+ qCDebug(Memory) << Q_FUNC_INFO << "rendering frame " << renderViews.last()->frameIndex() << " Queue " << m_renderQueues->queuedFrames();
for (int i = 0; i < renderViewsCount; i++) {
// Set the Viewport
m_graphicsContext->setViewport(renderViews[i]->viewport());
// Set RenderTarget ...
// Initialize QGraphicsContext for drawing
- executeCommands(renderViews[i]->commands());
+ executeCommands(renderViews.at(i)->commands());
+
+
frameElapsed = timer.elapsed() - frameElapsed;
qCDebug(Rendering) << Q_FUNC_INFO << "Submitted Renderview " << i + 1 << "/" << renderViewsCount << "in " << frameElapsed << "ms";
frameElapsed = timer.elapsed();
}
m_graphicsContext->endDrawing();
- // Clear QFrameAllocatorUsed by current RenderView so that it is properly cleaned for used by other frames
- // renderViews.last()->allocator()->clear();
- // The qDeleteAll will have to be removed
- qDeleteAll(renderViews);
+ m_renderQueues->popFrameQueue();
queueElapsed = timer.elapsed() - queueElapsed;
qCDebug(Rendering) << Q_FUNC_INFO << "Submission of Queue " << m_frameCount + 1 << "in " << queueElapsed << "ms <=> " << queueElapsed / renderViewsCount << "ms per RenderView <=> Avg " << 1000.0f / (queueElapsed * 1.0f/ renderViewsCount * 1.0f) << " RenderView/s";
qCDebug(Rendering) << Q_FUNC_INFO << "Queued frames for rendering remaining " << m_renderQueues->queuedFrames();;
@@ -440,12 +468,12 @@ QJobPtr Renderer::createRenderViewJob(FrameGraphNode *node, int submitOrderIndex
job->setRenderer(this);
job->setFrameGraphLeafNode(node);
job->setSubmitOrderIndex(submitOrderIndex);
- job->setFrameIndex(m_currentPreprocessingFrameIndex.loadAcquire());
+ job->setFrameIndex(m_currentPreprocessingFrameIndex);
return job;
}
// Called by RenderView->submit() in RenderThread context
-void Renderer::executeCommands(const QVector<RenderCommand *> commands)
+void Renderer::executeCommands(const QVector<RenderCommand *> &commands)
{
// Render drawing commands
diff --git a/src/render/backend/renderer.h b/src/render/backend/renderer.h
index bdcb2df5e..1386a6cc8 100644
--- a/src/render/backend/renderer.h
+++ b/src/render/backend/renderer.h
@@ -73,6 +73,9 @@ class Mesh;
class RenderPass;
class Shape;
class RendererAspect;
+class QFrameAllocator;
+
+typedef QVector<QFrameAllocator *> QFrameAllocatorQueue;
namespace Render {
@@ -129,7 +132,7 @@ public:
QVector<QJobPtr> createRenderBinJobs();
QJobPtr createRenderViewJob(FrameGraphNode *node, int submitOrderIndex);
- void executeCommands(const QVector<RenderCommand *> commands);
+ void executeCommands(const QVector<RenderCommand *> &commands);
inline RenderQueues* renderQueues() const { return m_renderQueues; }
inline MeshDataManager *meshDataManager() const { return m_meshDataManager; }
@@ -152,7 +155,7 @@ public:
inline HTechnique defaultTechniqueHandle() const { return m_defaultTechniqueHandle; }
inline HRenderPass defaultRenderPassHandle() const { return m_defaultRenderPassHandle; }
- inline const int cachedFramesCount() const { return m_cachedFramesCount; }
+ inline int cachedFramesCount() const { return m_cachedFramesCount; }
void buildMeshes(Mesh *mesh, Material *mat, const QMatrix4x4& mm);
void setSurface(QSurface *s);
@@ -162,6 +165,8 @@ public:
void initialize();
+ QFrameAllocator *currentFrameAllocator(int frameIndex);
+
QMutex* mutex() { return &m_mutex; }
private:
@@ -225,7 +230,9 @@ private:
QWaitCondition m_submitRenderViewsCondition;
uint m_frameCount;
QAtomicInt m_graphicContextInitialized;
- QAtomicInt m_currentPreprocessingFrameIndex;
+ int m_currentPreprocessingFrameIndex;
+
+ QThreadStorage< QPair<int, QFrameAllocatorQueue *> > m_tlsAllocators;
const int m_cachedFramesCount;
};
diff --git a/src/render/backend/renderqueues.cpp b/src/render/backend/renderqueues.cpp
index cf8a72d33..8807c9de6 100644
--- a/src/render/backend/renderqueues.cpp
+++ b/src/render/backend/renderqueues.cpp
@@ -85,6 +85,15 @@ void RenderQueues::queueRenderView(RenderView *renderView, uint submissionOrderI
}
/*!
+ * Called by the Rendering Thread to retrieve the a frame queue to render.
+ * A call to popFrameQueue is required after rendering of the frame.
+ */
+QVector<RenderView *> RenderQueues::nextFrameQueue()
+{
+ return m_queues.front();
+}
+
+/*!
* Sets the number \a targetRenderViewCount of RenderView objects that make up a frame.
*/
void RenderQueues::setTargetRenderViewCount(int targetRenderViewCount)
@@ -103,12 +112,12 @@ bool RenderQueues::isFrameQueueComplete() const
}
/*!
- * Called by the Rendering Thread to perform the rendering of the
- * first frame queue stored.
+ * Called by the Rendering Thread to pop the frame queue that has just been rendered
+ * and allow the Jobs to restart if the bounded circular buffer had reached its limit.
*/
-QVector<RenderView *> RenderQueues::popFrameQueue()
+void RenderQueues::popFrameQueue()
{
- return m_queues.pop_front();
+ m_queues.pop_front();
}
/*!
diff --git a/src/render/backend/renderqueues.h b/src/render/backend/renderqueues.h
index ba521d33c..63fd0d7e1 100644
--- a/src/render/backend/renderqueues.h
+++ b/src/render/backend/renderqueues.h
@@ -69,7 +69,8 @@ public:
int framesCapacity() const { return m_queues.capacity(); }
void queueRenderView(RenderView *renderView, uint submissionOrderIndex);
- QVector<RenderView *> popFrameQueue();
+ void popFrameQueue();
+ QVector<RenderView *> nextFrameQueue();
void pushFrameQueue();
void reset();
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index c61944d70..3c61041a4 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -72,6 +72,7 @@
#include <Qt3DCore/entity.h>
#include <Qt3DCore/qabstracteffect.h>
#include <Qt3DCore/qabstracttechnique.h>
+#include <Qt3DCore/qframeallocator.h>
#include <QDebug>
@@ -91,19 +92,104 @@ RenderView::standardUniformsPFuncsHash RenderView::initializeStandardUniformSett
setters[Parameter::ProjectionMatrix] = &RenderView::projectionMatrix;
setters[Parameter::ModelView] = &RenderView::modelViewMatrix;
setters[Parameter::ModelViewProjection] = &RenderView::modelViewProjectionMatrix;
- setters[Parameter::ModelInverse] = &RenderView::inversedModelMatrix;
- setters[Parameter::ViewInverse] = &RenderView::inversedViewMatrix;
- setters[Parameter::ProjectionInverse] = &RenderView::inversedProjectionMatrix;
- setters[Parameter::ModelViewInverse] = &RenderView::inversedModelViewMatrix;
- setters[Parameter::ModelViewProjectionInverse] = &RenderView::inversedModelViewProjectionMatrix;
+ setters[Parameter::ModelInverse] = &RenderView::inverseModelMatrix;
+ setters[Parameter::ViewInverse] = &RenderView::inverseViewMatrix;
+ setters[Parameter::ProjectionInverse] = &RenderView::inverseProjectionMatrix;
+ setters[Parameter::ModelViewInverse] = &RenderView::inverseModelViewMatrix;
+ setters[Parameter::ModelViewProjectionInverse] = &RenderView::inverseModelViewProjectionMatrix;
setters[Parameter::ModelNormal] = &RenderView::modelNormalMatrix;
setters[Parameter::ModelViewNormal] = &RenderView::modelViewNormalMatrix;
return setters;
}
+QUniformValue *RenderView::modelMatrix(RenderCamera *, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(model);
+ return t;
+}
+
+QUniformValue *RenderView::viewMatrix(RenderCamera *c, const QMatrix4x4 &) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->viewMatrix());
+ return t;
+}
+
+QUniformValue *RenderView::projectionMatrix(RenderCamera *c, const QMatrix4x4 &) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->projection());
+ return t;
+}
+
+QUniformValue *RenderView::modelViewMatrix(RenderCamera *c, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->viewMatrix() * model);
+ return t;
+}
+
+QUniformValue *RenderView::modelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->projection() * c->viewMatrix() * model);
+ return t;
+}
+
+QUniformValue *RenderView::inverseModelMatrix(RenderCamera *, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(model.inverted());
+ return t;
+}
+
+QUniformValue *RenderView::inverseViewMatrix(RenderCamera *c, const QMatrix4x4 &) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->viewMatrix().inverted());
+ return t;
+}
+
+QUniformValue *RenderView::inverseProjectionMatrix(RenderCamera *c, const QMatrix4x4 &) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue(c->projection().inverted());
+ return t;
+}
+
+QUniformValue *RenderView::inverseModelViewMatrix(RenderCamera *c, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue((c->viewMatrix() * model).inverted());
+ return t;
+}
+
+QUniformValue *RenderView::inverseModelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix4x4> *t = m_allocator->allocate<SpecifiedUniform<QMatrix4x4> >();
+ t->setValue((c->projection() * c->viewMatrix() * model).inverted());
+ return t;
+}
+
+QUniformValue *RenderView::modelNormalMatrix(RenderCamera *, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix3x3> *t = m_allocator->allocate<SpecifiedUniform<QMatrix3x3> >();
+ t->setValue(model.normalMatrix());
+ return t;
+}
+
+QUniformValue *RenderView::modelViewNormalMatrix(RenderCamera *c, const QMatrix4x4 &model) const
+{
+ SpecifiedUniform<QMatrix3x3> *t = m_allocator->allocate<SpecifiedUniform<QMatrix3x3> >();
+ t->setValue((c->viewMatrix() * model).normalMatrix());
+ return t;
+}
+
RenderView::RenderView()
: m_renderer(Q_NULLPTR)
+ , m_allocator(Q_NULLPTR)
, m_renderCamera(Q_NULLPTR)
, m_techniqueFilter(0)
, m_passFilter(0)
@@ -111,11 +197,6 @@ RenderView::RenderView()
{
}
-RenderView::~RenderView()
-{
- qDeleteAll(m_commands);
-}
-
void RenderView::setConfigFromFrameGraphLeafNode(FrameGraphNode *fgLeaf)
{
// The specific RenderPass to be used is also dependent upon the Effect and TechniqueFilter
@@ -186,6 +267,11 @@ void RenderView::setRenderer(Renderer *renderer)
m_renderer = renderer;
}
+void RenderView::setAllocator(QFrameAllocator *allocator)
+{
+ m_allocator = allocator;
+}
+
// Traverse Scene graphTree or culledSceneGraphTree
// ideally m_commands has been sized properly after the
// scene has been culled to the number of nodes in the culled
@@ -225,7 +311,7 @@ void RenderView::buildRenderCommands(RenderNode *node)
QHash<QString, QVariant> parameters = parametersFromMaterialEffectTechnique(material, effect, technique);
Q_FOREACH (RenderRenderPass *pass, passes) {
- RenderCommand *command = new RenderCommand();
+ RenderCommand *command = m_allocator->allocate<RenderCommand>();
command->m_mesh = meshHandle;
command->m_meshData = mesh->meshData();
command->m_instancesCount = 0;
@@ -426,10 +512,12 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, RenderRenderPass *
(tex = value.value<Qt3D::Texture*>()) != Q_NULLPTR) {
createRenderTexture(tex);
command->m_uniforms.setTexture(binding->shaderVariableName(), tex->uuid());
- command->m_uniforms.setUniform(binding->shaderVariableName(), new TextureUniform(tex->uuid()));
+ TextureUniform *texUniform = m_allocator->allocate<TextureUniform>();
+ texUniform->setTextureId(tex->uuid());
+ command->m_uniforms.setUniform(binding->shaderVariableName(), texUniform);
}
else {
- command->m_uniforms.setUniform(binding->shaderVariableName(), QUniformValue::fromVariant(value));
+ command->m_uniforms.setUniform(binding->shaderVariableName(), QUniformValue::fromVariant(value, m_allocator));
}
}
else if (binding->bindingType() == ParameterMapper::StandardUniform)
diff --git a/src/render/backend/renderview.h b/src/render/backend/renderview.h
index a0c7da6d6..5c2539f58 100644
--- a/src/render/backend/renderview.h
+++ b/src/render/backend/renderview.h
@@ -53,7 +53,8 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
-class RenderPass; // TODO Split into front/back ends
+class RenderPass;
+class QFrameAllocator;
namespace Render {
@@ -76,7 +77,6 @@ class Q_AUTOTEST_EXPORT RenderView
{
public:
RenderView();
- ~RenderView();
void setConfigFromFrameGraphLeafNode(FrameGraphNode *fgLeaf);
@@ -90,13 +90,16 @@ public:
// TODO: Add RenderTarget
void setRenderer(Renderer *renderer);
-
+ void setAllocator(QFrameAllocator *allocator);
void buildRenderCommands(RenderNode *node);
QVector<RenderCommand *> commands() const { return m_commands; }
inline QRectF viewport() const { return m_viewport; }
+ void setFrameIndex(int frameIndex) { m_frameIndex = frameIndex; }
+ int frameIndex() const { return m_frameIndex; }
+
private:
void computeViewport(ViewportNode *viewportNode);
@@ -109,11 +112,14 @@ private:
QHash<QString, QVariant> parametersFromMaterialEffectTechnique(RenderMaterial *material, RenderEffect *effect, RenderTechnique *technique);
Renderer *m_renderer;
+ QFrameAllocator *m_allocator;
RenderCamera *m_renderCamera;
TechniqueFilter *m_techniqueFilter;
RenderPassFilter *m_passFilter;
QRectF m_viewport;
+ int m_frameIndex;
+
// We do not use pointers to RenderNodes or Drawable's here so that the
// render aspect is free to change the drawables on the next frame whilst
// the render thread is submitting these commands.
@@ -129,18 +135,18 @@ private:
static standardUniformsPFuncsHash m_standardUniformSetters;
static standardUniformsPFuncsHash initializeStandardUniformSetters();
- inline QUniformValue *modelMatrix(RenderCamera *, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>(model); }
- inline QUniformValue *viewMatrix(RenderCamera *c, const QMatrix4x4&) const { return new SpecifiedUniform<QMatrix4x4>(c->viewMatrix());}
- inline QUniformValue *projectionMatrix(RenderCamera *c, const QMatrix4x4&) const { return new SpecifiedUniform<QMatrix4x4>(c->projection()); }
- inline QUniformValue *modelViewMatrix(RenderCamera *c, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>(c->viewMatrix() * model); }
- inline QUniformValue *modelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>(c->projection() * c->viewMatrix() * model); }
- inline QUniformValue *inversedModelMatrix(RenderCamera *, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>(model.inverted()); }
- inline QUniformValue *inversedViewMatrix(RenderCamera *c, const QMatrix4x4&) const { return new SpecifiedUniform<QMatrix4x4>(c->viewMatrix().inverted()); }
- inline QUniformValue *inversedProjectionMatrix(RenderCamera *c, const QMatrix4x4&) const { return new SpecifiedUniform<QMatrix4x4>(c->projection().inverted()); }
- inline QUniformValue *inversedModelViewMatrix(RenderCamera *c, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>((c->viewMatrix() * model).inverted()); }
- inline QUniformValue *inversedModelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix4x4>((c->projection() * c->viewMatrix() * model).inverted()); }
- inline QUniformValue *modelNormalMatrix(RenderCamera *, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix3x3>(model.normalMatrix()); }
- inline QUniformValue *modelViewNormalMatrix(RenderCamera *c, const QMatrix4x4& model) const { return new SpecifiedUniform<QMatrix3x3>((c->viewMatrix() * model).normalMatrix()); }
+ QUniformValue *modelMatrix(RenderCamera *, const QMatrix4x4& model) const;
+ QUniformValue *viewMatrix(RenderCamera *c, const QMatrix4x4&) const;
+ QUniformValue *projectionMatrix(RenderCamera *c, const QMatrix4x4 &) const;
+ QUniformValue *modelViewMatrix(RenderCamera *c, const QMatrix4x4 &model) const;
+ QUniformValue *modelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4 &model) const;
+ QUniformValue *inverseModelMatrix(RenderCamera *, const QMatrix4x4 &model) const;
+ QUniformValue *inverseViewMatrix(RenderCamera *c, const QMatrix4x4 &) const;
+ QUniformValue *inverseProjectionMatrix(RenderCamera *c, const QMatrix4x4 &) const;
+ QUniformValue *inverseModelViewMatrix(RenderCamera *c, const QMatrix4x4 &model) const;
+ QUniformValue *inverseModelViewProjectionMatrix(RenderCamera *c, const QMatrix4x4 &model) const;
+ QUniformValue *modelNormalMatrix(RenderCamera *, const QMatrix4x4 &model) const;
+ QUniformValue *modelViewNormalMatrix(RenderCamera *c, const QMatrix4x4 &model) const;
};
} // namespace Render
diff --git a/src/render/renderlogging.cpp b/src/render/renderlogging.cpp
index c17c011ad..57a3b46be 100644
--- a/src/render/renderlogging.cpp
+++ b/src/render/renderlogging.cpp
@@ -54,6 +54,7 @@ Q_LOGGING_CATEGORY(Jobs, "Qt3D.Render.Jobs")
Q_LOGGING_CATEGORY(Framegraph, "Qt3D.Render.Framegraph")
Q_LOGGING_CATEGORY(RenderNodes, "Qt3D.Render.RenderNodes")
Q_LOGGING_CATEGORY(Rendering, "Qt3D.Render.Rendering")
+Q_LOGGING_CATEGORY(Memory, "Qt3D.Render.Memory")
} // Render
diff --git a/src/render/renderlogging.h b/src/render/renderlogging.h
index fd44e4094..2f5774016 100644
--- a/src/render/renderlogging.h
+++ b/src/render/renderlogging.h
@@ -57,6 +57,7 @@ Q_DECLARE_LOGGING_CATEGORY(Jobs)
Q_DECLARE_LOGGING_CATEGORY(Framegraph)
Q_DECLARE_LOGGING_CATEGORY(RenderNodes)
Q_DECLARE_LOGGING_CATEGORY(Rendering)
+Q_DECLARE_LOGGING_CATEGORY(Memory)
} // Render