diff options
author | Sean Harmer <sean.harmer@kdab.com> | 2014-08-19 14:54:50 +0100 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2014-11-10 14:37:23 +0100 |
commit | 9a6ba985ca5274adc3f31d23e6ee9dc52379f282 (patch) | |
tree | fb198af7120c870d477a867b4d00fea9ca898b9f | |
parent | 9b9266405e8fa44a4546fd645d37874276cd9f41 (diff) | |
download | qt3d-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.cpp | 121 | ||||
-rw-r--r-- | src/render/backend/jobs/renderviewjob.h | 4 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 2 | ||||
-rw-r--r-- | src/render/backend/renderview.cpp | 122 | ||||
-rw-r--r-- | src/render/backend/renderview_p.h | 108 |
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; |