diff options
author | Svenn-Arne Dragly <s@dragly.com> | 2018-10-15 19:21:34 +0200 |
---|---|---|
committer | Andy Nichols <andy.nichols@qt.io> | 2018-10-16 07:19:05 +0000 |
commit | 7f75012d2efd597605eb031660d8929c6a3bcb04 (patch) | |
tree | 48df9930c38b7b23d99a79d87fcb9209cf53f61c | |
parent | 39e41cedc7cca3bf951177d9afb6e5960a981280 (diff) |
Add support for the Dragon render aspect in Studio3D
The Dragon render aspect can be enabled by setting
dragonRenderAspectEnabled: true
on a Presentation item.
Change-Id: Ic21b5493d1bdfc4a1de9ff4a4ad643b2ad72c7ed
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r-- | src/imports/studio3d/q3dsstudio3ditem.cpp | 3 | ||||
-rw-r--r-- | src/imports/studio3d/q3dsstudio3drenderer.cpp | 29 | ||||
-rw-r--r-- | src/imports/studio3d/q3dsstudio3drenderer_p.h | 7 | ||||
-rw-r--r-- | src/runtime/api/q3dspresentation.cpp | 35 | ||||
-rw-r--r-- | src/runtime/api/q3dspresentation.h | 5 | ||||
-rw-r--r-- | src/runtime/api/q3dspresentation_p.h | 4 | ||||
-rw-r--r-- | src/runtime/dragon/dragonactivatedsurface.cpp | 10 | ||||
-rw-r--r-- | src/runtime/dragon/dragonactivatedsurface_p.h | 5 | ||||
-rw-r--r-- | src/runtime/dragon/dragonrenderer.cpp | 57 | ||||
-rw-r--r-- | src/runtime/dragon/dragonrenderer_p.h | 16 | ||||
-rw-r--r-- | src/runtime/dragon/qdragonrenderaspect.cpp | 14 | ||||
-rw-r--r-- | src/runtime/dragon/qdragonrenderaspect_p.h | 5 | ||||
-rw-r--r-- | src/runtime/q3dsengine.cpp | 2 |
13 files changed, 152 insertions, 40 deletions
diff --git a/src/imports/studio3d/q3dsstudio3ditem.cpp b/src/imports/studio3d/q3dsstudio3ditem.cpp index 25a4d8c..381b88a 100644 --- a/src/imports/studio3d/q3dsstudio3ditem.cpp +++ b/src/imports/studio3d/q3dsstudio3ditem.cpp @@ -427,6 +427,9 @@ void Q3DSStudio3DItem::createEngine() if (m_sourceFlags.testFlag(Q3DSPresentationController::Profiling)) flags |= Q3DSEngine::EnableProfiling; + if (m_sourceFlags.testFlag(Q3DSPresentationController::AwakenTheDragon)) + flags |= Q3DSEngine::AwakenTheDragon; + m_engine->setFlags(flags); m_engine->setAutoToggleProfileUi(false); // up to the app to control this via the API instead diff --git a/src/imports/studio3d/q3dsstudio3drenderer.cpp b/src/imports/studio3d/q3dsstudio3drenderer.cpp index 7ea2163..d0d1399 100644 --- a/src/imports/studio3d/q3dsstudio3drenderer.cpp +++ b/src/imports/studio3d/q3dsstudio3drenderer.cpp @@ -33,6 +33,7 @@ #include <private/q3dslayer3dsgnode_p.h> #include <private/q3dsengine_p.h> #include <private/q3dslogging_p.h> +#include <private/qdragonrenderaspect_p.h> #include <QQuickWindow> #include <QOpenGLContext> #include <QGuiApplication> @@ -87,10 +88,16 @@ Q3DSStudio3DRenderer::Q3DSStudio3DRenderer(Q3DSStudio3DItem *item, Q3DSLayer3DSG this, &Q3DSStudio3DRenderer::renderOffscreen, Qt::DirectConnection); ContextSaver saver; - m_renderAspect = new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous); - m_aspectEngine->registerAspect(m_renderAspect); - m_renderAspectD = static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect)); - m_renderAspectD->renderInitialize(ctx); + if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon)) { + m_dragonRenderAspect = new Qt3DRender::Dragon::QDragonRenderAspect(Qt3DRender::Dragon::Renderer::Synchronous); + m_dragonRenderAspect->initialize(ctx); + m_aspectEngine->registerAspect(m_dragonRenderAspect); + } else { + m_renderAspect = new Qt3DRender::QRenderAspect(Qt3DRender::QRenderAspect::Synchronous); + m_aspectEngine->registerAspect(m_renderAspect); + m_renderAspectD = static_cast<Qt3DRender::QRenderAspectPrivate *>(Qt3DRender::QRenderAspectPrivate::get(m_renderAspect)); + m_renderAspectD->renderInitialize(ctx); + } QMetaObject::invokeMethod(m_item, "startEngine"); @@ -102,7 +109,9 @@ Q3DSStudio3DRenderer::~Q3DSStudio3DRenderer() { qCDebug(lcStudio3D, "[R] renderer %p dtor", this); ContextSaver saver; - m_renderAspectD->renderShutdown(); + + if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon)) + m_renderAspectD->renderShutdown(); } void Q3DSStudio3DRenderer::invalidateItem() @@ -148,7 +157,12 @@ void Q3DSStudio3DRenderer::renderOffscreen() ContextSaver saver; w->resetOpenGLState(); m_fbo->bind(); - m_renderAspectD->renderSynchronous(); + + if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon)) + m_currentFrame = m_dragonRenderAspect->renderSynchronous(std::move(m_currentFrame)); + else + m_renderAspectD->renderSynchronous(); + if (saver.context()->surface() != saver.surface()) saver.context()->makeCurrent(saver.surface()); w->resetOpenGLState(); @@ -156,6 +170,9 @@ void Q3DSStudio3DRenderer::renderOffscreen() if (m_node) { m_node->markDirty(QSGNode::DirtyMaterial); } else { + if (m_item->engine()->flags().testFlag(Q3DSEngine::AwakenTheDragon)) + qFatal("View3D is not yet supported in the Dragon render aspect."); + QSharedPointer<Qt3DRender::Render::ResourceAccessor> ra = m_renderAspectD->m_renderer->nodeManagers()->resourceAccessor(); if (ra) { for (auto vd : m_viewDesc) { diff --git a/src/imports/studio3d/q3dsstudio3drenderer_p.h b/src/imports/studio3d/q3dsstudio3drenderer_p.h index e2c1ce1..6508be7 100644 --- a/src/imports/studio3d/q3dsstudio3drenderer_p.h +++ b/src/imports/studio3d/q3dsstudio3drenderer_p.h @@ -46,6 +46,7 @@ #include <QElapsedTimer> #include <QOpenGLFramebufferObject> #include <QSGTexture> +#include <private/dragonrenderer_p.h> #include "q3dsstudio3dviewdesc_p.h" QT_BEGIN_NAMESPACE @@ -61,6 +62,9 @@ class QAspectEngine; namespace Qt3DRender { class QRenderAspect; class QRenderAspectPrivate; +namespace Dragon { +class QDragonRenderAspect; +} } class Q3DSStudio3DRenderer : public QObject @@ -92,6 +96,7 @@ private: Qt3DCore::QAspectEngine *m_aspectEngine; Qt3DRender::QRenderAspect *m_renderAspect = nullptr; Qt3DRender::QRenderAspectPrivate *m_renderAspectD = nullptr; + Qt3DRender::Dragon::QDragonRenderAspect *m_dragonRenderAspect = nullptr; QScopedPointer<QSGTexture> m_texture; QScopedPointer<QOpenGLFramebufferObject> m_fbo; @@ -100,6 +105,8 @@ private: QVector<Q3DSStudio3DViewDesc> m_viewDesc; QElapsedTimer m_renderTimer; bool m_usingRenderThread; + + Qt3DRender::Dragon::Renderer::Frame m_currentFrame; }; QT_END_NAMESPACE diff --git a/src/runtime/api/q3dspresentation.cpp b/src/runtime/api/q3dspresentation.cpp index 6c502e1..3a8e37e 100644 --- a/src/runtime/api/q3dspresentation.cpp +++ b/src/runtime/api/q3dspresentation.cpp @@ -169,6 +169,38 @@ void Q3DSPresentation::setProfilingEnabled(bool enable) } /*! + \property Q3DSPresentation::dragonRenderAspectEnabled + + When enabled, the new, experimental Qt3D render aspect + (codenamed "Dragon") is enabled. + This render aspect will replace the original render aspect + in a future release. + This property will be deprecated once the aspect has been + replaced. + + The default value is \c false. + + \note Changing the value after the presentation has been loaded + has no effect for the already loaded presentation. Therefore the + changing of this property must happen before calling setSource(). +*/ +bool Q3DSPresentation::isDragonRenderAspectEnabled() const +{ + Q_D(const Q3DSPresentation); + return d->dragonRenderAspectEnabled; +} + +void Q3DSPresentation::setDragonRenderAspectEnabled(bool dragonRenderAspectEnabled) +{ + Q_D(Q3DSPresentation); + if (d->dragonRenderAspectEnabled == dragonRenderAspectEnabled) + return; + + d->dragonRenderAspectEnabled = dragonRenderAspectEnabled; + emit dragonRenderAspectEnabledChanged(); +} + +/*! \property Q3DSPresentation::profileUiVisible When this property is \c{true}, the interactive statistics and profile @@ -616,6 +648,9 @@ Q3DSPresentationController::SourceFlags Q3DSPresentationPrivate::sourceFlags() c if (profiling) flags |= Q3DSPresentationController::Profiling; + if (dragonRenderAspectEnabled) + flags |= Q3DSPresentationController::AwakenTheDragon; + return flags; } diff --git a/src/runtime/api/q3dspresentation.h b/src/runtime/api/q3dspresentation.h index 085ce89..898eef8 100644 --- a/src/runtime/api/q3dspresentation.h +++ b/src/runtime/api/q3dspresentation.h @@ -56,6 +56,7 @@ class Q3DSV_EXPORT Q3DSPresentation : public QObject Q_PROPERTY(bool profilingEnabled READ isProfilingEnabled WRITE setProfilingEnabled NOTIFY profilingEnabledChanged) Q_PROPERTY(bool profileUiVisible READ isProfileUiVisible WRITE setProfileUiVisible NOTIFY profileUiVisibleChanged) Q_PROPERTY(float profileUiScale READ profileUiScale WRITE setProfileUiScale NOTIFY profileUiScaleChanged) + Q_PROPERTY(bool dragonRenderAspectEnabled READ isDragonRenderAspectEnabled WRITE setDragonRenderAspectEnabled NOTIFY dragonRenderAspectEnabledChanged) public: explicit Q3DSPresentation(QObject *parent = nullptr); @@ -73,6 +74,9 @@ public: float profileUiScale() const; void setProfileUiScale(float scale); + bool isDragonRenderAspectEnabled() const; + void setDragonRenderAspectEnabled(bool dragonRenderAspectEnabled); + Q_INVOKABLE void reload(); Q_INVOKABLE void setDataInputValue(const QString &name, const QVariant &value); @@ -109,6 +113,7 @@ Q_SIGNALS: void customSignalEmitted(const QString &elementPath, const QString &name); void slideEntered(const QString &elementPath, int index, const QString &name); void slideExited(const QString &elementPath, int index, const QString &name); + void dragonRenderAspectEnabledChanged(); protected: Q3DSPresentation(Q3DSPresentationPrivate &dd, QObject *parent); diff --git a/src/runtime/api/q3dspresentation_p.h b/src/runtime/api/q3dspresentation_p.h index b056c0c..63c0f9a 100644 --- a/src/runtime/api/q3dspresentation_p.h +++ b/src/runtime/api/q3dspresentation_p.h @@ -59,7 +59,8 @@ public: void initializePresentationController(Q3DSEngine *engine, Q3DSPresentation *presentation); enum SourceFlag { - Profiling = 0x01 + Profiling = 0x01, + AwakenTheDragon = 0x02 }; Q_DECLARE_FLAGS(SourceFlags, SourceFlag) @@ -119,6 +120,7 @@ public: bool profileUiVisible = false; float profileUiScale = 1.0f; QVector<Q3DSInlineQmlSubPresentation *> inlineQmlSubPresentations; + bool dragonRenderAspectEnabled = false; }; QT_END_NAMESPACE diff --git a/src/runtime/dragon/dragonactivatedsurface.cpp b/src/runtime/dragon/dragonactivatedsurface.cpp index 2657be9..e485759 100644 --- a/src/runtime/dragon/dragonactivatedsurface.cpp +++ b/src/runtime/dragon/dragonactivatedsurface.cpp @@ -420,9 +420,9 @@ void ActivatedSurface::applyUniform(const ShaderUniform &description, const Unif } } -DrawContext ActivatedSurface::beginDrawing() +DrawContext ActivatedSurface::beginDrawing(bool autoSwapBuffers) { - return DrawContext(m_glContext, m_surface); + return DrawContext(m_glContext, m_surface, autoSwapBuffers); } UniformValue standardUniformValue(StandardUniform standardUniformType, @@ -1661,14 +1661,16 @@ void ActivatedSurface::blitFramebuffer(const BlitFramebufferInfo &blitFramebuffe } } -DrawContext::DrawContext(QOpenGLContext *openGLContext, QSurface *surface) +DrawContext::DrawContext(QOpenGLContext *openGLContext, QSurface *surface, bool autoSwapBuffers) : m_openGLContext(openGLContext) , m_surface(surface) + , m_autoSwapBuffers(autoSwapBuffers) { } DrawContext::~DrawContext() { - m_openGLContext->swapBuffers(m_surface); + if (m_autoSwapBuffers) + m_openGLContext->swapBuffers(m_surface); } #define QT3D_DRAGON_UNIFORM_TYPE_IMPL(UniformTypeEnum, BaseType, Func) \ diff --git a/src/runtime/dragon/dragonactivatedsurface_p.h b/src/runtime/dragon/dragonactivatedsurface_p.h index 65e8fe0..dbccf57 100644 --- a/src/runtime/dragon/dragonactivatedsurface_p.h +++ b/src/runtime/dragon/dragonactivatedsurface_p.h @@ -89,9 +89,10 @@ class DrawContext public: ~DrawContext(); private: - DrawContext(QOpenGLContext *openGLContext, QSurface *surface); + DrawContext(QOpenGLContext *openGLContext, QSurface *surface, bool autoSwapBuffers); QOpenGLContext *m_openGLContext = nullptr; QSurface *m_surface = nullptr; + bool m_autoSwapBuffers = true; friend class ActivatedSurface; }; @@ -160,7 +161,7 @@ public: // Parameter/uniform functions void applyUniform(const ShaderUniform &description, const UniformValue &v); - DrawContext beginDrawing(); + DrawContext beginDrawing(bool autoSwapBuffers); void blitFramebuffer(const BlitFramebufferInfo &blitFramebufferInfo, uint defaultFboId, const MutableContainer<GLTexture> &glTextures); private: diff --git a/src/runtime/dragon/dragonrenderer.cpp b/src/runtime/dragon/dragonrenderer.cpp index afd0089..175534c 100644 --- a/src/runtime/dragon/dragonrenderer.cpp +++ b/src/runtime/dragon/dragonrenderer.cpp @@ -132,10 +132,11 @@ a Renderer for each backend. */ -Renderer::Renderer() +Renderer::Renderer(RenderType renderType) : nextFrameSemaphore(1) - , m_renderThread(new RenderThread(this)) + , m_renderThread(renderType == Threaded ? new RenderThread(this) : nullptr) , m_running(1) + , m_renderType(renderType) { if (m_renderThread) m_renderThread->waitForStart(); @@ -160,20 +161,31 @@ Renderer::~Renderer() m_renderThread->wait(); } m_offscreenHelper->deleteLater(); + if (m_ownedContext) + m_glContext->deleteLater(); } -void Renderer::initialize() +/*! + * \internal + * \brief Renderer::initialize + * + * If a context is provided to this function, it will be used for rendering, + * which is the case for Studio3D and Scene3D items. + */ +void Renderer::initialize(QOpenGLContext *context) { - // TODO don't forget to delete this - m_glContext = new QOpenGLContext; - m_glContext->setShareContext(qt_gl_global_share_context()); - m_glContext->create(); - // if (m_glContext->create()) - // qCDebug(Render::Backend) << "OpenGL context created with actual format" - // << m_glContext->format(); - // else - // qCWarning(Render::Backend) << Q_FUNC_INFO << "OpenGL context creation failed"; - m_ownedContext = true; + if (context != nullptr) { + m_glContext = context; + } else { + m_glContext = new QOpenGLContext; + m_glContext->setShareContext(qt_gl_global_share_context()); + + if (!m_glContext->create()) + qWarning() << Q_FUNC_INFO << "OpenGL context creation failed"; + + m_ownedContext = true; + } + if (!m_glContext->shareContext()) { // TODO don't forget to delete this m_shareContext = new QOpenGLContext; @@ -367,6 +379,8 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame) continue; } + const GLuint fboBeforeRender = activeSurface.glHelper()->boundFrameBufferObject(); + // We only need to do preparations such as uploading textures for one surface if (!preparationsComplete) { { @@ -483,6 +497,12 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame) } } + { + GLRenderTarget renderTarget; + renderTarget.frameBufferObjectId = fboBeforeRender; + frame.createdRenderTargets[QNodeId()] = renderTarget; + } + // Create render target if (!view->renderTargetId.isNull()) { auto defaultFBO = m_glContext->defaultFramebufferObject(); @@ -491,7 +511,8 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame) auto lastBoundFBOId = activeSurface.glHelper()->boundFrameBufferObject(); const auto &renderTargetNodeId = view->renderTargetId; const auto &attachments = view->attachmentPack; - if (!frame.createdRenderTargets.contains(view->renderTargetId)) { + + if (!frame.createdRenderTargets.contains(renderTargetNodeId)) { GLRenderTarget renderTarget; if (defaultFBO != 0 && lastBoundFBOId == defaultFBO) { // this is the default fbo that some platforms create (iOS), @@ -558,7 +579,9 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame) if (!preparationsComplete) return frame; - DrawContext drawContext = activeSurface.beginDrawing(); + // TODO might be better to just have to call swapBuffers manually + bool autoSwapBuffers = m_renderType == RenderType::Threaded; + DrawContext drawContext = activeSurface.beginDrawing(autoSwapBuffers); // TODO consider what m_ownCurrent was used for in SubmissionContext @@ -592,9 +615,7 @@ Renderer::Frame Renderer::doRender(Renderer::Frame frame) // TODO handle render state set // TODO consider having this function return a render target that is passed to the following functions - activeSurface.activateRenderTarget(frame.createdRenderTargets[view->renderTargetId] - .frameBufferObjectId, - view->attachmentPack); + activeSurface.activateRenderTarget(frame.createdRenderTargets[view->renderTargetId].frameBufferObjectId, view->attachmentPack); activeSurface.clearBackBuffer(view->clearBackBufferInfo); // TODO make it return a viewport, used by other functions that need one diff --git a/src/runtime/dragon/dragonrenderer_p.h b/src/runtime/dragon/dragonrenderer_p.h index dc8f627..c040819 100644 --- a/src/runtime/dragon/dragonrenderer_p.h +++ b/src/runtime/dragon/dragonrenderer_p.h @@ -134,7 +134,7 @@ struct GLRenderTarget class Renderer { -private: +public: /*! * \brief The Frame struct holds data that is shared across frames, * such as already uploaded textures and active textures. @@ -152,8 +152,14 @@ private: int number = 0; }; -public: - Renderer(); + // TODO a cleaner option is to move all thread-specific code into a separate class + // instead of letting one class handle both cases + enum RenderType { + Synchronous, + Threaded + }; + + Renderer(RenderType renderType); ~Renderer(); void render(); @@ -163,7 +169,7 @@ public: void addLatestData(FrameInput data); GraphicsApiFilterData contextInfo(RenderViews views); - void initialize(); + void initialize(QOpenGLContext *context = nullptr); QSemaphore nextFrameSemaphore; @@ -206,6 +212,8 @@ private: OffscreenSurfaceHelper *m_offscreenHelper; + RenderType m_renderType; + // // Shaders // Render::ShaderCache *m_shaderCache = nullptr; diff --git a/src/runtime/dragon/qdragonrenderaspect.cpp b/src/runtime/dragon/qdragonrenderaspect.cpp index 3427068..f82c1f5 100644 --- a/src/runtime/dragon/qdragonrenderaspect.cpp +++ b/src/runtime/dragon/qdragonrenderaspect.cpp @@ -187,8 +187,8 @@ QT_BEGIN_NAMESPACE namespace Qt3DRender { namespace Dragon { -QDragonRenderAspect::QDragonRenderAspect() - : m_renderer(new Renderer()) +QDragonRenderAspect::QDragonRenderAspect(Renderer::RenderType renderType) + : m_renderer(new Renderer(renderType)) { registerBackendType<Qt3DCore::QEntity>(m_entities); registerBackendType<Qt3DCore::QTransform>(m_transforms); @@ -512,6 +512,16 @@ QVector<Qt3DCore::QAspectJobPtr> QDragonRenderAspect::jobsToExecute(qint64 time) return m_jobs; } +Renderer::Frame QDragonRenderAspect::renderSynchronous(Renderer::Frame frame) +{ + return m_renderer->doRender(std::move(frame)); +} + +void QDragonRenderAspect::initialize(QOpenGLContext *context) +{ + m_renderer->initialize(context); +} + } // namespace Dragon } // namespace Qt3DRender QT_END_NAMESPACE diff --git a/src/runtime/dragon/qdragonrenderaspect_p.h b/src/runtime/dragon/qdragonrenderaspect_p.h index d60f759..32cb559 100644 --- a/src/runtime/dragon/qdragonrenderaspect_p.h +++ b/src/runtime/dragon/qdragonrenderaspect_p.h @@ -114,9 +114,10 @@ class Q3DSV_EXPORT QDragonRenderAspect : public Qt3DCore::QAbstractAspect { Q_OBJECT public: - QDragonRenderAspect(); + QDragonRenderAspect(Renderer::RenderType renderType); + Renderer::Frame renderSynchronous(Renderer::Frame frame); + void initialize(QOpenGLContext *context); - // QAbstractAspect interface private: QVector<Qt3DCore::QAspectJobPtr> jobsToExecute(qint64 time) override; diff --git a/src/runtime/q3dsengine.cpp b/src/runtime/q3dsengine.cpp index 500c8fa..16c49ef 100644 --- a/src/runtime/q3dsengine.cpp +++ b/src/runtime/q3dsengine.cpp @@ -390,7 +390,7 @@ void Q3DSEngine::createAspectEngine() if (!m_flags.testFlag(WithoutRenderAspect)) { m_renderLoopStats.usingAsyncRenderAspect = true; if (m_flags.testFlag(AwakenTheDragon)) - m_aspectEngine->registerAspect(new Qt3DRender::Dragon::QDragonRenderAspect); + m_aspectEngine->registerAspect(new Qt3DRender::Dragon::QDragonRenderAspect(Qt3DRender::Dragon::Renderer::Threaded)); else m_aspectEngine->registerAspect(new Qt3DRender::QRenderAspect); } else { |