summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Harmer <sean.harmer@kdab.com>2014-08-19 14:54:50 +0100
committerSean Harmer <sean.harmer@kdab.com>2014-11-10 14:37:23 +0100
commit9a6ba985ca5274adc3f31d23e6ee9dc52379f282 (patch)
treefb198af7120c870d477a867b4d00fea9ca898b9f
parent9b9266405e8fa44a4546fd645d37874276cd9f41 (diff)
downloadqt3d-9a6ba985ca5274adc3f31d23e6ee9dc52379f282.tar.gz
Move renderview configuration from fg into a free function
Change-Id: I89c4031972c3520cd36a99d11bdf7e5fb71ad99f Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/render/backend/jobs/renderviewjob.cpp121
-rw-r--r--src/render/backend/jobs/renderviewjob.h4
-rw-r--r--src/render/backend/renderer.cpp2
-rw-r--r--src/render/backend/renderview.cpp122
-rw-r--r--src/render/backend/renderview_p.h108
5 files changed, 222 insertions, 135 deletions
diff --git a/src/render/backend/jobs/renderviewjob.cpp b/src/render/backend/jobs/renderviewjob.cpp
index eebb79b52..cefaec6ba 100644
--- a/src/render/backend/jobs/renderviewjob.cpp
+++ b/src/render/backend/jobs/renderviewjob.cpp
@@ -41,8 +41,19 @@
#include "renderviewjob.h"
+#include <Qt3DRenderer/sphere.h>
+
+#include <Qt3DRenderer/private/clearbuffer_p.h>
#include <Qt3DRenderer/private/renderview_p.h>
#include <Qt3DRenderer/private/renderer_p.h>
+#include <Qt3DRenderer/private/cameraselectornode_p.h>
+#include <Qt3DRenderer/private/managers_p.h>
+#include <Qt3DRenderer/private/layerfilternode_p.h>
+#include <Qt3DRenderer/private/renderpassfilternode_p.h>
+#include <Qt3DRenderer/private/rendertargetselectornode_p.h>
+#include <Qt3DRenderer/private/sortmethod_p.h>
+#include <Qt3DRenderer/private/techniquefilternode_p.h>
+#include <Qt3DRenderer/private/viewportnode_p.h>
#include "renderlogging.h"
@@ -51,6 +62,110 @@ QT_BEGIN_NAMESPACE
namespace Qt3D {
namespace Render {
+/*!
+ \internal
+ Walks up the framegraph tree from \p fgLeaf and builds up as much state
+ as possible and populates \p rv. For cases where we can't get the specific state
+ (e.g. because it depends upon more than just the framegraph) we store the data from
+ the framegraph that will be needed to later when the rest of the data becomes available
+*/
+void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphNode *fgLeaf)
+{
+ // The specific RenderPass to be used is also dependent upon the Effect and TechniqueFilter
+ // which is referenced by the Material which is referenced by the RenderMesh. So we can
+ // only store the filter info in the RenderView structure and use it to do the resolving
+ // when we build the RenderCommand list.
+ const Renderer *renderer = rv->renderer();
+ const FrameGraphNode *node = fgLeaf;
+
+ while (node) {
+ FrameGraphNode::FrameGraphNodeType type = node->nodeType();
+ switch (type) {
+ case FrameGraphNode::CameraSelector:
+ // Can be set only once and we take camera nearest to the leaf node
+ if (!rv->renderCamera()) {
+ const CameraSelector *cameraSelector = static_cast<const CameraSelector *>(node);
+ RenderEntity *camNode = renderer->renderNodesManager()->lookupResource(cameraSelector->cameraUuid());
+ if (camNode) {
+ rv->setRenderCamera(camNode->renderComponent<RenderCameraLens>());
+ rv->setViewMatrix(*camNode->worldTransform());
+
+ // TODO: We can extract camera pos from the modelview matrix
+ rv->setEyePosition(camNode->worldBoundingVolume()->center());
+ }
+ break;
+ }
+
+ case FrameGraphNode::LayerFilter: // Can be set multiple times in the tree
+ rv->appendLayerFilter(static_cast<const LayerFilterNode *>(node)->layers());
+ break;
+
+ case FrameGraphNode::RenderPassFilter:
+ // Can be set once
+ // TODO: Amalgamate all render pass filters from leaf to root
+ if (!rv->renderPassFilter())
+ rv->setRenderPassFilter(static_cast<const RenderPassFilter *>(node));
+ break;
+
+ case FrameGraphNode::RenderTarget: {
+ // Can be set once and we take render target nearest to the leaf node
+ QNodeUuid renderTargetUid = static_cast<const RenderTargetSelector *>(node)->renderTargetUuid();
+ HTarget renderTargetHandle = renderer->renderTargetManager()->lookupHandle(renderTargetUid);
+ if (rv->renderTargetHandle().isNull()) {
+ rv->setRenderTargetHandle(renderTargetHandle);
+
+ RenderTarget *renderTarget = renderer->renderTargetManager()->data(renderTargetHandle);
+ if (renderTarget) {
+ // Add renderTarget Handle and build renderCommand AttachmentPack
+ Q_FOREACH (const QNodeUuid &attachmentId, renderTarget->renderAttachments()) {
+ RenderAttachment *attachment = renderer->attachmentManager()->lookupResource(attachmentId);
+ if (attachment)
+ rv->addRenderAttachment(attachment->attachment());
+ }
+ }
+ }
+ break;
+ }
+
+ case FrameGraphNode::ClearBuffer:
+ rv->setClearBuffer(static_cast<const ClearBuffer *>(node)->type());
+ break;
+
+ case FrameGraphNode::TechniqueFilter:
+ // Can be set once
+ // TODO Amalgamate all technique filters from leaf to root
+ if (rv->techniqueFilter())
+ rv->setTechniqueFilter(static_cast<const TechniqueFilter *>(node));
+ break;
+
+ case FrameGraphNode::Viewport: {
+ // If the Viewport has already been set in a lower node
+ // Make it so that the new viewport is actually
+ // a subregion relative to that of the parent viewport
+ const ViewportNode *vpNode = static_cast<const ViewportNode *>(node);
+ rv->setViewport(computeViewport(rv->viewport(), vpNode));
+
+ // We take the clear color from the viewport node nearest the leaf
+ if (!rv->clearColor().isValid())
+ rv->setClearColor(vpNode->clearColor());
+ break;
+ }
+
+ case FrameGraphNode::SortMethod: {
+ const Render::SortMethod *sortMethod = static_cast<const Render::SortMethod *>(node);
+ rv->addSortCriteria(sortMethod->criteria());
+ break;
+ }
+
+ default:
+ // Should never get here
+ qCWarning(Backend) << "Unhandled FrameGraphNode type";
+ }
+
+ node = node->parent();
+ }
+}
+
void RenderViewJob::run()
{
qCDebug(Jobs) << Q_FUNC_INFO << m_index << " frame " << m_frameIndex;
@@ -65,9 +180,9 @@ void RenderViewJob::run()
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);
+
+ // Populate the renderview's configuration from the framegraph
+ setRenderViewConfigFromFrameGraphLeafNode(renderView, m_fgLeaf);
// Gather resources needed for buildRenderCommand
// Ex lights, we need all lights in the scene before we can buildRenderCommands
diff --git a/src/render/backend/jobs/renderviewjob.h b/src/render/backend/jobs/renderviewjob.h
index 281f68534..10824fdf7 100644
--- a/src/render/backend/jobs/renderviewjob.h
+++ b/src/render/backend/jobs/renderviewjob.h
@@ -53,8 +53,12 @@ namespace Qt3D {
namespace Render {
class Renderer;
+class RenderView;
class FrameGraphNode;
+Q_AUTOTEST_EXPORT void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv,
+ const FrameGraphNode *fgLeaf);
+
class RenderViewJob : public QAspectJob
{
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 581044d50..f088721d4 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -520,7 +520,7 @@ void Renderer::submitRenderViews()
for (int i = 0; i < renderViewsCount; i++) {
// Set RenderTarget ...
// Activate RenderTarget
- m_graphicsContext->activateRenderTarget(m_renderTargetManager->data(renderViews[i]->renderTarget()),
+ m_graphicsContext->activateRenderTarget(m_renderTargetManager->data(renderViews[i]->renderTargetHandle()),
renderViews[i]->attachmentPack());
// Clear BackBuffer
m_graphicsContext->clearBackBuffer(renderViews[i]->clearBuffer());
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index ccc04eb02..b41e3d1c6 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -46,6 +46,7 @@
#include <Qt3DRenderer/renderlogging.h>
#include <Qt3DRenderer/qtexture.h>
#include <Qt3DRenderer/qrendertarget.h>
+#include <Qt3DRenderer/sphere.h>
#include <Qt3DRenderer/private/cameraselectornode_p.h>
#include <Qt3DRenderer/private/framegraphnode_p.h>
@@ -64,10 +65,6 @@
#include <Qt3DRenderer/private/renderrenderpass_p.h>
#include <Qt3DRenderer/private/techniquefilternode_p.h>
#include <Qt3DRenderer/private/viewportnode_p.h>
-#include <Qt3DRenderer/private/rendertargetselectornode_p.h>
-#include <Qt3DRenderer/private/clearbuffer_p.h>
-#include <Qt3DRenderer/private/sortmethod_p.h>
-#include <Qt3DRenderer/sphere.h>
#include <Qt3DRenderer/qparametermapping.h>
#include <Qt3DRenderer/qalphatest.h>
@@ -84,7 +81,6 @@
#include <Qt3DRenderer/private/blendstate_p.h>
#include <Qt3DCore/qentity.h>
-#include <Qt3DCore/qframeallocator.h>
#include <QtGui/qsurface.h>
@@ -265,22 +261,27 @@ RenderView::RenderView()
, m_clearColor(Q_NULLPTR)
, m_viewport(Q_NULLPTR)
, m_clearBuffer(QClearBuffer::None)
+ , m_commands()
{
}
RenderView::~RenderView()
{
if (m_allocator == Q_NULLPTR) // Mainly needed for unit tests
- return ;
+ return;
+
Q_FOREACH (RenderCommand *command, m_commands) {
// Deallocate all uniform values of the QUniformPack of each RenderCommand
Q_FOREACH (const QUniformValue *v, command->m_uniforms.uniforms().values())
m_allocator->deallocate<QUniformValue>(const_cast<QUniformValue *>(v));
- if (command->m_stateSet != Q_NULLPTR) // We do not delete the RenderState as there are stored statically
+
+ if (command->m_stateSet != Q_NULLPTR) // We do not delete the RenderState as that is stored statically
m_allocator->deallocate<RenderStateSet>(command->m_stateSet);
+
// Deallocate RenderCommand
m_allocator->deallocate<RenderCommand>(command);
}
+
// Deallocate viewMatrix
m_allocator->deallocate<QMatrix4x4>(m_data->m_viewMatrix);
// Deallocate viewport rect
@@ -308,96 +309,6 @@ void RenderView::operator delete(void *ptr, void *)
rView->m_allocator->deallocateRawMemory<RenderView>(rView);
}
-void RenderView::setConfigFromFrameGraphLeafNode(FrameGraphNode *fgLeaf)
-{
- // The specific RenderPass to be used is also dependent upon the Effect and TechniqueFilter
- // which is referenced by the Material which is referenced by the RenderMesh. So we can
- // only store the filter info in the RenderView structure and use it to do the resolving
- // when we build the RenderCommand list.
- FrameGraphNode *node = fgLeaf;
- while (node != Q_NULLPTR) {
- FrameGraphNode::FrameGraphNodeType type = node->nodeType();
- switch (type) {
- case FrameGraphNode::CameraSelector: // Can be set once
- if (m_data->m_renderCamera == Q_NULLPTR) {
- CameraSelector *cameraSelector = static_cast<CameraSelector *>(node);
- RenderEntity *tmpCamNode = m_renderer->renderNodesManager()->lookupResource(cameraSelector->cameraUuid());
- if (tmpCamNode) {
- m_data->m_renderCamera = tmpCamNode->renderComponent<RenderCameraLens>();
- // If we have a viewMatrix pointer instead of directly a QMatrix4x4 object in RenderView
- // This allows us to keep the size of RenderView smaller and avoid huge block fragmentation
- *m_data->m_viewMatrix = *tmpCamNode->worldTransform();
- m_data->m_eyePos = tmpCamNode->worldBoundingVolume()->center();
- }
- break;
- }
-
- case FrameGraphNode::LayerFilter: // Can be set multiple times in the tree
- m_data->m_layers << static_cast<LayerFilterNode *>(node)->layers();
- break;
-
- case FrameGraphNode::RenderPassFilter:
- if (m_data->m_passFilter == Q_NULLPTR) // Can be set once
- m_data->m_passFilter = static_cast<RenderPassFilter *>(node);
- break;
-
- case FrameGraphNode::RenderTarget:
- if (m_renderTarget.isNull()) // Can be set once
- m_renderTarget = m_renderer->renderTargetManager()->lookupHandle(static_cast<RenderTargetSelector *>(node)->renderTargetUuid());
- RenderTarget *renderTarget;
- if ((renderTarget = m_renderer->renderTargetManager()->data(m_renderTarget)) != Q_NULLPTR) {
- // Add renderTarget Handle and build renderCommand AttachmentPack
- Q_FOREACH (const QNodeUuid &attachmentId, renderTarget->renderAttachments()) {
- RenderAttachment *attachment = m_renderer->attachmentManager()->lookupResource(attachmentId);
- if (attachment != Q_NULLPTR)
- m_attachmentPack.addAttachment(attachment->attachment());
- }
- }
- break;
-
- case FrameGraphNode::ClearBuffer:
- m_clearBuffer = static_cast<ClearBuffer *>(node)->type();
- break;
-
- case FrameGraphNode::TechniqueFilter:
- if (m_data->m_techniqueFilter == Q_NULLPTR) // Can be set once
- m_data->m_techniqueFilter = static_cast<TechniqueFilter *>(node);
- break;
-
- case FrameGraphNode::Viewport: {
- // If the Viewport has already been set in a lower node
- // Make it so that the new viewport is actually
- // a subregion relative to that of the parent viewport
- if (!m_viewport) {
- m_viewport = m_allocator->allocate<QRectF>();
- *m_viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f);
- }
- ViewportNode *vpNode = static_cast<ViewportNode *>(node);
- *m_viewport = computeViewport(*m_viewport, vpNode);
-
- // We take the clear color from the viewport node nearest the leaf
- if (!m_clearColor)
- m_clearColor = m_allocator->allocate<QColor>();
- if (!m_clearColor->isValid())
- *m_clearColor = vpNode->clearColor();
- break;
- }
-
- case FrameGraphNode::SortMethod:
- Render::SortMethod *sM;
- sM = static_cast<Render::SortMethod *>(node);
- m_data->m_sortingCriteria.append(sM->criteria());
- break;
-
- default:
- // Should never get here
- qCWarning(Backend) << "Unhandled FrameGraphNode type";
- }
-
- node = node->parent();
- }
-}
-
void RenderView::sort()
{
// Compares the bitsetKey of the RenderCommands
@@ -406,18 +317,6 @@ void RenderView::sort()
std::sort(m_commands.begin(), m_commands.end());
}
-void RenderView::setRenderer(Renderer *renderer)
-{
- m_renderer = renderer;
-}
-
-void RenderView::setAllocator(QFrameAllocator *allocator)
-{
- m_allocator = allocator;
- m_data = m_allocator->allocate<InnerData>();
- m_data->m_viewMatrix = m_allocator->allocate<QMatrix4x4>();
-}
-
void RenderView::preprocessRenderTree(RenderEntity *node)
{
// Retrieve light for the currentNode and append it to list of current lights
@@ -487,11 +386,6 @@ const AttachmentPack &RenderView::attachmentPack() const
return m_attachmentPack;
}
-HTarget RenderView::renderTarget() const
-{
- return m_renderTarget;
-}
-
RenderTechnique *RenderView::findTechniqueForEffect(RenderEffect *effect)
{
if (effect != Q_NULLPTR) {
diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h
index 7a2339387..fd2afe26c 100644
--- a/src/render/backend/renderview_p.h
+++ b/src/render/backend/renderview_p.h
@@ -49,6 +49,10 @@
#include <Qt3DRenderer/private/rendercameralens_p.h>
#include <Qt3DRenderer/private/attachmentpack_p.h>
#include <Qt3DRenderer/private/handle_types_p.h>
+#include <Qt3DRenderer/qparameter.h>
+
+#include <Qt3DCore/qframeallocator.h>
+
#include <QVector>
#include <QMutex>
#include <QColor>
@@ -83,19 +87,87 @@ public:
static void operator delete(void *ptr);
static void operator delete(void *ptr, void *);
- void setConfigFromFrameGraphLeafNode(FrameGraphNode *fgLeaf);
-
// TODO: Add a way to specify a sort predicate for the RenderCommands
void sort();
- // These pointers define the configuration that needs to be
- // set for this RenderView before it's contained RenderCommands
- // can be submitted. If a pointer is null, that pice of state
- // does not need to be changed.
- // TODO: Add RenderTarget
+ inline void setRenderer(Renderer *renderer) { m_renderer = renderer; }
+ inline Renderer *renderer() const { return m_renderer; }
+
+ inline void setAllocator(QFrameAllocator *allocator)
+ {
+ m_allocator = allocator;
+ m_data = m_allocator->allocate<InnerData>();
+ // If we have a viewMatrix pointer instead of directly a QMatrix4x4 object in RenderView
+ // This allows us to keep the size of RenderView smaller and avoid huge block fragmentation
+ //
+ // TODO: Is this worth it here. We don't have that many RenderViews to iterate over. This
+ // level of memory management would be better in RenderEntity's matrices as they will
+ // help cache performance during iteration
+ m_data->m_viewMatrix = m_allocator->allocate<QMatrix4x4>();
+ }
+ inline QFrameAllocator *allocator() const { return m_allocator; }
+
+ inline void setRenderCamera(RenderCameraLens *renderCamera) { m_data->m_renderCamera = renderCamera; }
+ inline RenderCameraLens *renderCamera() const { return m_data->m_renderCamera; }
- void setRenderer(Renderer *renderer);
- void setAllocator(QFrameAllocator *allocator);
+ inline void setViewMatrix(const QMatrix4x4 viewMatrix) { *(m_data->m_viewMatrix) = viewMatrix; }
+ inline QMatrix4x4 viewmatrix() const { Q_ASSERT(m_data->m_viewMatrix); return *(m_data->m_viewMatrix); }
+
+ inline void setEyePosition(const QVector3D &eyePos) { m_data->m_eyePos = eyePos; }
+ inline QVector3D eyePosition() const { return m_data->m_eyePos; }
+
+ inline void appendLayerFilter(const QStringList &layers) { m_data->m_layers << layers; }
+ inline QStringList layerFilters() const { return m_data->m_layers; }
+
+ inline void setRenderPassFilter(const RenderPassFilter *rpFilter) { m_data->m_passFilter = rpFilter; }
+ inline const RenderPassFilter *renderPassFilter() const { return m_data->m_passFilter; }
+
+ inline void setTechniqueFilter(const TechniqueFilter *filter) { m_data->m_techniqueFilter = filter; }
+ inline const TechniqueFilter *techniqueFilter() const { return m_data->m_techniqueFilter; }
+
+ // TODO: Get rid of this overly complex memory management by splitting out the
+ // InnerData as a RenderViewConfig struct. This can be created by setRenderViewConfigFromFrameGraphLeafNode
+ // and passed along with the RenderView to the functions that populate the renderview
+ inline void setViewport(const QRectF &vp)
+ {
+ if (!m_viewport) {
+ Q_ASSERT(m_allocator);
+ m_viewport = m_allocator->allocate<QRectF>();
+ *m_viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f);
+ }
+ *m_viewport = vp;
+ }
+ inline QRectF viewport() const
+ {
+ if (!m_viewport) {
+ Q_ASSERT(m_allocator);
+ m_viewport = m_allocator->allocate<QRectF>();
+ *m_viewport = QRectF(0.0f, 0.0f, 1.0f, 1.0f);
+ }
+ return *m_viewport;
+ }
+
+ inline void setClearColor(const QColor &c)
+ {
+ if (!m_clearColor) {
+ Q_ASSERT(m_allocator);
+ m_clearColor = m_allocator->allocate<QColor>();
+ *m_clearColor = QColor(QColor::Invalid);
+ }
+ *m_clearColor = c;
+ }
+ inline QColor clearColor() const
+ {
+ if (!m_clearColor) {
+ Q_ASSERT(m_allocator);
+ m_clearColor = m_allocator->allocate<QColor>();
+ *m_clearColor = QColor(QColor::Invalid);
+ }
+ return *m_clearColor;
+ }
+
+ inline void setClearBuffer(QClearBuffer::BufferType clearBuffer) { m_clearBuffer = clearBuffer; }
+ inline QClearBuffer::BufferType clearBuffer() const { return m_clearBuffer; }
// Gather resources
void preprocessRenderTree(RenderEntity *sceneGraphRoot);
@@ -103,16 +175,18 @@ public:
void buildRenderCommands(RenderEntity *preprocessedTreeRoot);
QVector<RenderCommand *> commands() const { return m_commands; }
- inline QRectF viewport() const { return *m_viewport; }
- inline QColor clearColor() const { return *m_clearColor; }
- inline QClearBuffer::BufferType clearBuffer() const { return m_clearBuffer; }
// This can be removed once we're 100% sure the QFrameAllocator is death proof
void setFrameIndex(int index) { m_frameIndex = index; }
int frameIndex() const { return m_frameIndex; }
+ void addRenderAttachment(Attachment attachment) { m_attachmentPack.addAttachment(attachment); }
const AttachmentPack &attachmentPack() const;
- HTarget renderTarget() const;
+
+ void setRenderTargetHandle(HTarget renderTargetHandle) { m_renderTarget = renderTargetHandle; }
+ HTarget renderTargetHandle() const { return m_renderTarget; }
+
+ void addSortCriteria(const QList<QNodeUuid> &sortMethodUid) { m_data->m_sortingCriteria.append(sortMethodUid); }
private:
RenderTechnique *findTechniqueForEffect(RenderEffect *effect);
@@ -136,8 +210,8 @@ private:
{
}
RenderCameraLens *m_renderCamera;
- TechniqueFilter *m_techniqueFilter;
- RenderPassFilter *m_passFilter;
+ const TechniqueFilter *m_techniqueFilter;
+ const RenderPassFilter *m_passFilter;
QMatrix4x4 *m_viewMatrix;
QStringList m_layers;
QList<LightPair> m_lights;
@@ -145,8 +219,8 @@ private:
QVector3D m_eyePos;
} *m_data;
- QColor *m_clearColor;
- QRectF *m_viewport;
+ mutable QColor *m_clearColor;
+ mutable QRectF *m_viewport;
HTarget m_renderTarget;
AttachmentPack m_attachmentPack;
QClearBuffer::BufferType m_clearBuffer;