diff options
Diffstat (limited to 'src/render/backend')
23 files changed, 2 insertions, 6604 deletions
diff --git a/src/render/backend/commandthread.cpp b/src/render/backend/commandthread.cpp deleted file mode 100644 index 387fc1113..000000000 --- a/src/render/backend/commandthread.cpp +++ /dev/null @@ -1,195 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "commandthread_p.h" -#include <Qt3DRender/private/glcommands_p.h> -#include <Qt3DRender/private/offscreensurfacehelper_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/shadercache_p.h> -#include <QOpenGLContext> -#include <QOffscreenSurface> -#include <QDebug> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -CommandThread::CommandThread(Renderer *renderer) - : QThread() - , m_renderer(renderer) - , m_waitForStartSemaphore(0) - , m_initializedSemaphore(0) - , m_commandRequestedSemaphore(0) - , m_commandExecutionSemaphore(0) - , m_mainContext(nullptr) - , m_shaderCache(nullptr) - , m_offsreenSurfaceHelper(nullptr) - , m_currentCommand(nullptr) - , m_running(0) -{ -} - -CommandThread::~CommandThread() -{ -} - -void CommandThread::setShaderCache(ShaderCache *shaderCache) -{ - m_shaderCache = shaderCache; -} - -// Called by RenderThread or MainThread (Scene3d) -void CommandThread::initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper) -{ - // Start the thread - start(); - - // Wait for thread to be started - m_waitForStartSemaphore.acquire(); - - m_mainContext = mainContext; - m_offsreenSurfaceHelper = offsreenSurfaceHelper; - Q_ASSERT(m_mainContext && offsreenSurfaceHelper); - m_running.fetchAndStoreOrdered(1); - - // Allow thread to proceed - m_initializedSemaphore.release(); -} - -// Called by RenderThread or MainThread (Scene3D) -void CommandThread::shutdown() -{ - m_running.fetchAndStoreOrdered(0); - - // Unblock thread - m_commandRequestedSemaphore.release(1); - - // Wait for thread to exit - wait(); - - // Reset semaphores (in case we ever want to restart) - m_waitForStartSemaphore.acquire(m_waitForStartSemaphore.available()); - m_initializedSemaphore.acquire(m_initializedSemaphore.available()); - m_commandRequestedSemaphore.acquire(m_commandRequestedSemaphore.available()); - m_commandExecutionSemaphore.acquire(m_commandExecutionSemaphore.available()); - m_localContext.reset(); -} - -// Any thread can call this, this is a blocking command -void CommandThread::executeCommand(GLCommand *command) -{ - if (!isRunning()) - return; - - // We lock to prevent any other call to executeCommand to be executed - // before we have received the result of our command - m_blockingCallerMutex.lock(); - - // Store command to be executed - m_currentCommand = command; - - // Allow thread to proceed and execute command - m_commandRequestedSemaphore.release(); - - // Wait for thread to be done - m_commandExecutionSemaphore.acquire(); - - // Reset command - m_currentCommand = nullptr; - - // Unlock blocking semaphore so that other calls to executeCommand - // can proceed - m_blockingCallerMutex.unlock(); -} - -void CommandThread::run() -{ - // Allow initialize to proceed - m_waitForStartSemaphore.release(); - - // Wait for initialize to be completed - m_initializedSemaphore.acquire(); - - Q_ASSERT(m_mainContext && m_shaderCache); - - // Initialize shared context and resources for the thread - m_localContext.reset(new QOpenGLContext()); - m_localContext->setShareContext(m_mainContext); - m_localContext->create(); - - // Initialize GraphicsContext - m_graphicsContext.reset(new GraphicsContext()); - m_graphicsContext->setShaderCache(m_shaderCache); - m_graphicsContext->setOpenGLContext(m_localContext.data()); - - bool initialized = false; - while (true) { - - // Wait for command - m_commandRequestedSemaphore.acquire(); - - // Are we still running? - if (!m_running.load()) { - m_graphicsContext->doneCurrent(); - // to prevent executeCommand being locked - m_commandExecutionSemaphore.release(); - break; - } - - if (Q_UNLIKELY(!initialized)) { - QOffscreenSurface *offscreenSurface = m_offsreenSurfaceHelper->offscreenSurface(); - Q_ASSERT(offscreenSurface); - m_graphicsContext->makeCurrent(offscreenSurface); - initialized = true; - } - - m_currentCommand->execute(m_renderer, m_graphicsContext.data()); - - // Allow caller to proceed as we are done with the command - m_commandExecutionSemaphore.release(); - } -} - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/commandthread_p.h b/src/render/backend/commandthread_p.h deleted file mode 100644 index 0508675c4..000000000 --- a/src/render/backend/commandthread_p.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_COMMANDTHREAD_P_H -#define QT3DRENDER_RENDER_COMMANDTHREAD_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtCore/QThread> -#include <QtCore/QSemaphore> -#include <QtCore/QMutex> - -QT_BEGIN_NAMESPACE - -class QOpenGLContext; - -namespace Qt3DRender { - -namespace Render { - -class Renderer; -class GLCommand; -class OffscreenSurfaceHelper; -class GraphicsContext; -class ShaderCache; - -class CommandThread : public QThread -{ - Q_OBJECT -public: - explicit CommandThread(Renderer *renderer); - ~CommandThread(); - - Render::Renderer* renderer() const { return m_renderer; } - - void setShaderCache(ShaderCache *shaderCache); - ShaderCache *shaderCache() const { return m_shaderCache; } - - void initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper); - void shutdown(); - - void executeCommand(GLCommand *command); - -private: - void run() override; - void executeCommandInternal(Qt3DRender::Render::GLCommand *command); - -private: - Renderer* m_renderer; - QSemaphore m_waitForStartSemaphore; - QSemaphore m_initializedSemaphore; - QSemaphore m_commandRequestedSemaphore; - QSemaphore m_commandExecutionSemaphore; - QMutex m_blockingCallerMutex; - QOpenGLContext *m_mainContext; - ShaderCache *m_shaderCache; - OffscreenSurfaceHelper *m_offsreenSurfaceHelper; - QScopedPointer<QOpenGLContext> m_localContext; - QScopedPointer<GraphicsContext> m_graphicsContext; - GLCommand *m_currentCommand; - QAtomicInt m_running; -}; - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_COMMANDTHREAD_P_H diff --git a/src/render/backend/glcommands.cpp b/src/render/backend/glcommands.cpp deleted file mode 100644 index fd7ee9fe8..000000000 --- a/src/render/backend/glcommands.cpp +++ /dev/null @@ -1,67 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "glcommands_p.h" -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -LoadShaderCommand::LoadShaderCommand(Shader *shader) - : m_shader(shader) -{ - Q_ASSERT(m_shader); -} - -void LoadShaderCommand::execute(Renderer *renderer, GraphicsContext *ctx) -{ - NodeManagers *nodeManagers = renderer->nodeManagers(); - ctx->loadShader(m_shader, nodeManagers->shaderManager()); -} - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/glcommands_p.h b/src/render/backend/glcommands_p.h deleted file mode 100644 index 5ed360759..000000000 --- a/src/render/backend/glcommands_p.h +++ /dev/null @@ -1,89 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_GLCOMMANDS_P_H -#define QT3DRENDER_RENDER_GLCOMMANDS_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DRender/qt3drender_global.h> - -QT_BEGIN_NAMESPACE - - -namespace Qt3DRender { - -namespace Render { - -class GraphicsContext; -class Renderer; -class Shader; - -class GLCommand -{ -public: - virtual void execute(Renderer *renderer, GraphicsContext *ctx) = 0; -}; - -class Q_AUTOTEST_EXPORT LoadShaderCommand : public GLCommand -{ -public: - explicit LoadShaderCommand(Shader *shader); - Shader *shader() const { return m_shader; } - void execute(Renderer *renderer, GraphicsContext *ctx) Q_DECL_OVERRIDE; - -private: - Shader *m_shader = nullptr; -}; -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_GLCOMMANDS_P_H diff --git a/src/render/backend/openglvertexarrayobject.cpp b/src/render/backend/openglvertexarrayobject.cpp deleted file mode 100644 index 0c4fd8c9d..000000000 --- a/src/render/backend/openglvertexarrayobject.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "openglvertexarrayobject_p.h" -#include <Qt3DRender/private/submissioncontext_p.h> -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DRender/private/managers_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -OpenGLVertexArrayObject::OpenGLVertexArrayObject() - : m_ctx(nullptr) - , m_specified(false) - , m_supportsVao(false) -{} - -void OpenGLVertexArrayObject::bind() -{ - Q_ASSERT(m_ctx); - if (m_supportsVao) { - Q_ASSERT(!m_vao.isNull()); - Q_ASSERT(m_vao->isCreated()); - m_vao->bind(); - } else { - // Unbind any other VAO that may have been bound and not released correctly - if (m_ctx->m_currentVAO != nullptr && m_ctx->m_currentVAO != this) - m_ctx->m_currentVAO->release(); - - m_ctx->m_currentVAO = this; - // We need to specify array and vertex attributes - for (const SubmissionContext::VAOVertexAttribute &attr : qAsConst(m_vertexAttributes)) - m_ctx->enableAttribute(attr); - if (!m_indexAttribute.isNull()) - m_ctx->bindGLBuffer(m_ctx->m_renderer->nodeManagers()->glBufferManager()->data(m_indexAttribute), - GLBuffer::IndexBuffer); - } -} - -void OpenGLVertexArrayObject::release() -{ - Q_ASSERT(m_ctx); - if (m_supportsVao) { - Q_ASSERT(!m_vao.isNull()); - Q_ASSERT(m_vao->isCreated()); - m_vao->release(); - } else { - if (m_ctx->m_currentVAO == this) { - for (const SubmissionContext::VAOVertexAttribute &attr : qAsConst(m_vertexAttributes)) - m_ctx->disableAttribute(attr); - m_ctx->m_currentVAO = nullptr; - } - } -} - -// called from Render thread -void OpenGLVertexArrayObject::create(SubmissionContext *ctx, const VAOIdentifier &key) -{ - QMutexLocker lock(&m_mutex); - - Q_ASSERT(!m_ctx && !m_vao); - - m_ctx = ctx; - m_supportsVao = m_ctx->supportsVAO(); - if (m_supportsVao) { - m_vao.reset(new QOpenGLVertexArrayObject()); - m_vao->create(); - } - m_owners = key; -} - -// called from Render thread -void OpenGLVertexArrayObject::destroy() -{ - QMutexLocker locker(&m_mutex); - - Q_ASSERT(m_ctx); - cleanup(); -} - -void OpenGLVertexArrayObject::cleanup() -{ - m_vao.reset(); - m_ctx = nullptr; - m_specified = false; - m_supportsVao = false; - m_indexAttribute = SubmissionContext::VAOIndexAttribute(); - m_vertexAttributes.clear(); -} - -// called from job -bool OpenGLVertexArrayObject::isAbandoned(GeometryManager *geomMgr, ShaderManager *shaderMgr) -{ - QMutexLocker lock(&m_mutex); - - if (!m_ctx) - return false; - - const bool geometryExists = (geomMgr->data(m_owners.first) != nullptr); - const bool shaderExists = (shaderMgr->data(m_owners.second) != nullptr); - - return !geometryExists || !shaderExists; -} - -void OpenGLVertexArrayObject::saveVertexAttribute(const SubmissionContext::VAOVertexAttribute &attr) -{ - // Remove any vertexAttribute already at location - for (auto i = m_vertexAttributes.size() - 1; i >= 0; --i) { - if (m_vertexAttributes.at(i).location == attr.location) { - m_vertexAttributes.removeAt(i); - break; - } - } - m_vertexAttributes.push_back(attr); -} - - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/openglvertexarrayobject_p.h b/src/render/backend/openglvertexarrayobject_p.h deleted file mode 100644 index eee837221..000000000 --- a/src/render/backend/openglvertexarrayobject_p.h +++ /dev/null @@ -1,110 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2015 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef OPENGLVERTEXARRAYOBJECT_H -#define OPENGLVERTEXARRAYOBJECT_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QtGui/qopenglvertexarrayobject.h> -#include <Qt3DRender/private/submissioncontext_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -class GeometryManager; -class ShaderManager; - -typedef QPair<HGeometry, HShader> VAOIdentifier; - -class OpenGLVertexArrayObject -{ -public: - OpenGLVertexArrayObject(); - - void bind(); - void release(); - - void create(SubmissionContext *ctx, const VAOIdentifier &key); - void destroy(); - void cleanup(); - - bool isAbandoned(GeometryManager *geomMgr, ShaderManager *shaderMgr); - - QOpenGLVertexArrayObject *vao() { return m_vao.data(); } - const QOpenGLVertexArrayObject *vao() const { return m_vao.data(); } - - void setSpecified(bool b) { m_specified = b; } - bool isSpecified() const { return m_specified; } - - -private: - QMutex m_mutex; - SubmissionContext *m_ctx; - QScopedPointer<QOpenGLVertexArrayObject> m_vao; - bool m_specified; - bool m_supportsVao; - VAOIdentifier m_owners; - - friend class SubmissionContext; - - void saveVertexAttribute(const SubmissionContext::VAOVertexAttribute &attr); - inline void saveIndexAttribute(HGLBuffer glBufferHandle) { m_indexAttribute = glBufferHandle; } - - QVector<SubmissionContext::VAOVertexAttribute> m_vertexAttributes; - SubmissionContext::VAOIndexAttribute m_indexAttribute; -}; - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // OPENGLVERTEXARRAYOBJECT_H diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri index cde9e77b9..352de3be5 100644 --- a/src/render/backend/render-backend.pri +++ b/src/render/backend/render-backend.pri @@ -2,15 +2,9 @@ INCLUDEPATH += $$PWD HEADERS += \ $$PWD/renderthread_p.h \ - $$PWD/renderconfiguration_p.h \ - $$PWD/renderer_p.h \ - $$PWD/renderview_p.h \ - $$PWD/rendercommand_p.h \ - $$PWD/renderqueue_p.h \ $$PWD/parameterpack_p.h \ $$PWD/rendertarget_p.h \ $$PWD/attachmentpack_p.h \ - $$PWD/shadervariables_p.h \ $$PWD/qgraphicsutils_p.h \ $$PWD/managers_p.h \ $$PWD/handle_types_p.h \ @@ -24,7 +18,6 @@ HEADERS += \ $$PWD/boundingvolumedebug_p.h \ $$PWD/nodemanagers_p.h \ $$PWD/triangleboundingvolume_p.h \ - $$PWD/openglvertexarrayobject_p.h \ $$PWD/trianglesextractor_p.h \ $$PWD/buffervisitor_p.h \ $$PWD/bufferutils_p.h \ @@ -36,25 +29,15 @@ HEADERS += \ $$PWD/backendnode_p.h \ $$PWD/rendertargetoutput_p.h \ $$PWD/uniform_p.h \ - $$PWD/shaderparameterpack_p.h \ - $$PWD/renderviewbuilder_p.h \ $$PWD/frameprofiler_p.h \ $$PWD/offscreensurfacehelper_p.h \ $$PWD/resourceaccessor_p.h \ - $$PWD/commandthread_p.h \ $$PWD/visitorutils_p.h \ $$PWD/segmentsvisitor_p.h \ - $$PWD/pointsvisitor_p.h \ - $$PWD/renderercache_p.h \ - $$PWD/glcommands_p.h + $$PWD/pointsvisitor_p.h SOURCES += \ $$PWD/renderthread.cpp \ - $$PWD/renderconfiguration.cpp \ - $$PWD/renderer.cpp \ - $$PWD/renderview.cpp \ - $$PWD/rendercommand.cpp \ - $$PWD/renderqueue.cpp \ $$PWD/parameterpack.cpp \ $$PWD/rendertarget.cpp \ $$PWD/managers.cpp \ @@ -75,16 +58,11 @@ SOURCES += \ $$PWD/backendnode.cpp \ $$PWD/rendertargetoutput.cpp \ $$PWD/attachmentpack.cpp \ - $$PWD/openglvertexarrayobject.cpp \ $$PWD/uniform.cpp \ - $$PWD/shaderparameterpack.cpp \ - $$PWD/renderviewbuilder.cpp \ $$PWD/offscreensurfacehelper.cpp \ $$PWD/resourceaccessor.cpp \ $$PWD/segmentsvisitor.cpp \ - $$PWD/commandthread.cpp \ - $$PWD/pointsvisitor.cpp \ - $$PWD/glcommands.cpp + $$PWD/pointsvisitor.cpp include($$QT3D_BUILD_ROOT/src/core/qt3dcore-config.pri) QT_FOR_CONFIG += 3dcore-private diff --git a/src/render/backend/rendercommand.cpp b/src/render/backend/rendercommand.cpp deleted file mode 100644 index e60b17668..000000000 --- a/src/render/backend/rendercommand.cpp +++ /dev/null @@ -1,76 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "rendercommand_p.h" - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -RenderCommand::RenderCommand() - : m_stateSet(nullptr) - , m_depth(0.0f) - , m_changeCost(0) - , m_type(RenderCommand::Draw) - , m_primitiveCount(0) - , m_primitiveType(QGeometryRenderer::Triangles) - , m_restartIndexValue(-1) - , m_firstInstance(0) - , m_firstVertex(0) - , m_verticesPerPatch(0) - , m_instanceCount(0) - , m_indexOffset(0) - , m_indexAttributeByteOffset(0) - , m_indexAttributeDataType(GL_UNSIGNED_SHORT) - , m_indirectAttributeByteOffset(0) - , m_drawIndexed(false) - , m_drawIndirect(false) - , m_primitiveRestartEnabled(false) - , m_isValid(false) -{ - m_workGroups[0] = 0; - m_workGroups[1] = 0; - m_workGroups[2] = 0; -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/rendercommand_p.h b/src/render/backend/rendercommand_p.h deleted file mode 100644 index 67e02d35b..000000000 --- a/src/render/backend/rendercommand_p.h +++ /dev/null @@ -1,130 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERCOMMAND_H -#define QT3DRENDER_RENDER_RENDERCOMMAND_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qglobal.h> -#include <Qt3DRender/private/shaderparameterpack_p.h> -#include <Qt3DRender/private/handle_types_p.h> -#include <Qt3DRender/qgeometryrenderer.h> -#include <QOpenGLShaderProgram> -#include <QOpenGLTexture> -#include <QMatrix4x4> - -QT_BEGIN_NAMESPACE - -class QOpenGLVertexArrayObject; - -namespace Qt3DRender { - -namespace Render { - -class RenderStateSet; - -class Q_AUTOTEST_EXPORT RenderCommand -{ -public: - RenderCommand(); - - HVao m_vao; // VAO used during the submission step to store all states and VBOs - HShader m_shader; // Shader for given pass and mesh - HMaterial m_material; // Purely used to ease sorting (minimize stage changes, binding changes ....) - ShaderParameterPack m_parameterPack; // Might need to be reworked so as to be able to destroy the - // Texture while submission is happening. - RenderStateSet *m_stateSet; - - HGeometry m_geometry; - HGeometryRenderer m_geometryRenderer; - - HBuffer m_indirectDrawBuffer; // Reference to indirect draw buffer (valid only m_drawIndirect == true) - - // A QAttribute pack might be interesting - // This is a temporary fix in the meantime, to remove the hacked methods in Technique - QVector<int> m_attributes; - - float m_depth; - int m_changeCost; - uint m_shaderDna; - - enum CommandType { - Draw, - Compute - }; - - CommandType m_type; - int m_workGroups[3]; - - // Values filled for draw calls - GLsizei m_primitiveCount; - QGeometryRenderer::PrimitiveType m_primitiveType; - int m_restartIndexValue; - int m_firstInstance; - int m_firstVertex; - int m_verticesPerPatch; - int m_instanceCount; - int m_indexOffset; - uint m_indexAttributeByteOffset; - GLint m_indexAttributeDataType; - uint m_indirectAttributeByteOffset; - bool m_drawIndexed; - bool m_drawIndirect; - bool m_primitiveRestartEnabled; - bool m_isValid; -}; - -} // namespace Render - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERCOMMAND_H diff --git a/src/render/backend/renderconfiguration.cpp b/src/render/backend/renderconfiguration.cpp deleted file mode 100644 index 730676996..000000000 --- a/src/render/backend/renderconfiguration.cpp +++ /dev/null @@ -1,54 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "renderconfiguration_p.h" - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -RenderConfiguration::RenderConfiguration() -{ -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/renderconfiguration_p.h b/src/render/backend/renderconfiguration_p.h deleted file mode 100644 index 9aa950faa..000000000 --- a/src/render/backend/renderconfiguration_p.h +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERCONFIGURATION_H -#define QT3DRENDER_RENDER_RENDERCONFIGURATION_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <qglobal.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -class RenderConfiguration -{ -public: - RenderConfiguration(); -}; - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERCONFIGURATION_H diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp deleted file mode 100644 index 2611fb6cc..000000000 --- a/src/render/backend/renderer.cpp +++ /dev/null @@ -1,2067 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "renderer_p.h" - -#include <Qt3DCore/qentity.h> - -#include <Qt3DRender/qmaterial.h> -#include <Qt3DRender/qmesh.h> -#include <Qt3DRender/qrenderpass.h> -#include <Qt3DRender/qshaderprogram.h> -#include <Qt3DRender/qtechnique.h> -#include <Qt3DRender/qrenderaspect.h> -#include <Qt3DRender/qeffect.h> - -#include <Qt3DRender/private/qsceneimporter_p.h> -#include <Qt3DRender/private/renderstates_p.h> -#include <Qt3DRender/private/cameraselectornode_p.h> -#include <Qt3DRender/private/framegraphvisitor_p.h> -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/cameralens_p.h> -#include <Qt3DRender/private/rendercommand_p.h> -#include <Qt3DRender/private/entity_p.h> -#include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DRender/private/material_p.h> -#include <Qt3DRender/private/renderpassfilternode_p.h> -#include <Qt3DRender/private/renderqueue_p.h> -#include <Qt3DRender/private/shader_p.h> -#include <Qt3DRender/private/buffer_p.h> -#include <Qt3DRender/private/glbuffer_p.h> -#include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DRender/private/technique_p.h> -#include <Qt3DRender/private/renderthread_p.h> -#include <Qt3DRender/private/renderview_p.h> -#include <Qt3DRender/private/scenemanager_p.h> -#include <Qt3DRender/private/techniquefilternode_p.h> -#include <Qt3DRender/private/viewportnode_p.h> -#include <Qt3DRender/private/vsyncframeadvanceservice_p.h> -#include <Qt3DRender/private/pickeventfilter_p.h> -#include <Qt3DRender/private/managers_p.h> -#include <Qt3DRender/private/buffermanager_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DRender/private/gltexturemanager_p.h> -#include <Qt3DRender/private/gltexture_p.h> -#include <Qt3DRender/private/geometryrenderermanager_p.h> -#include <Qt3DRender/private/techniquemanager_p.h> -#include <Qt3DRender/private/openglvertexarrayobject_p.h> -#include <Qt3DRender/private/platformsurfacefilter_p.h> -#include <Qt3DRender/private/loadbufferjob_p.h> -#include <Qt3DRender/private/rendercapture_p.h> -#include <Qt3DRender/private/updatelevelofdetailjob_p.h> -#include <Qt3DRender/private/buffercapture_p.h> -#include <Qt3DRender/private/offscreensurfacehelper_p.h> -#include <Qt3DRender/private/renderviewbuilder_p.h> -#include <Qt3DRender/private/commandthread_p.h> -#include <Qt3DRender/private/glcommands_p.h> - -#include <Qt3DRender/qcameralens.h> -#include <Qt3DCore/private/qeventfilterservice_p.h> -#include <Qt3DCore/private/qabstractaspectjobmanager_p.h> -#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h> - -#if QT_CONFIG(qt3d_profile_jobs) -#include <Qt3DCore/private/aspectcommanddebugger_p.h> -#endif - -#include <QStack> -#include <QOffscreenSurface> -#include <QSurface> -#include <QElapsedTimer> -#include <QLibraryInfo> -#include <QPluginLoader> -#include <QDir> -#include <QUrl> -#include <QOffscreenSurface> -#include <QWindow> - -#include <QtGui/private/qopenglcontext_p.h> - -// For Debug purposes only -#include <QThread> - - -#if QT_CONFIG(qt3d_profile_jobs) -#include <Qt3DCore/private/qthreadpooler_p.h> -#include <Qt3DRender/private/job_common_p.h> -#include <Qt3DRender/private/commandexecuter_p.h> -#endif - -#include <Qt3DRender/private/frameprofiler_p.h> - -QT_BEGIN_NAMESPACE - -using namespace Qt3DCore; - -namespace Qt3DRender { -namespace Render { -/*! - \internal - - Renderer shutdown procedure: - - Since the renderer relies on the surface and OpenGLContext to perform its cleanup, - it is shutdown when the surface is set to nullptr - - When the surface is set to nullptr this will request the RenderThread to terminate - and will prevent createRenderBinJobs from returning a set of jobs as there is nothing - more to be rendered. - - In turn, this will call shutdown which will make the OpenGL context current one last time - to allow cleanups requiring a call to QOpenGLContext::currentContext to execute properly. - At the end of that function, the GraphicsContext is set to null. - - At this point though, the QAspectThread is still running its event loop and will only stop - a short while after. - */ - -Renderer::Renderer(QRenderAspect::RenderType type) - : m_services(nullptr) - , m_nodesManager(nullptr) - , m_renderSceneRoot(nullptr) - , m_defaultRenderStateSet(nullptr) - , m_submissionContext(nullptr) - , m_renderQueue(new RenderQueue()) - , m_renderThread(type == QRenderAspect::Threaded ? new RenderThread(this) : nullptr) - , m_commandThread(new CommandThread(this)) - , m_vsyncFrameAdvanceService(new VSyncFrameAdvanceService(m_renderThread != nullptr)) - , m_waitForInitializationToBeCompleted(0) - , m_pickEventFilter(new PickEventFilter()) - , m_exposed(0) - , m_lastFrameCorrect(0) - , m_glContext(nullptr) - , m_shareContext(nullptr) - , m_shaderCache(new ShaderCache()) - , m_pickBoundingVolumeJob(PickBoundingVolumeJobPtr::create()) - , m_rayCastingJob(RayCastingJobPtr::create()) - , m_time(0) - , m_settings(nullptr) - , m_updateShaderDataTransformJob(Render::UpdateShaderDataTransformJobPtr::create()) - , m_cleanupJob(Render::FrameCleanupJobPtr::create()) - , m_worldTransformJob(Render::UpdateWorldTransformJobPtr::create()) - , m_expandBoundingVolumeJob(Render::ExpandBoundingVolumeJobPtr::create()) - , m_calculateBoundingVolumeJob(Render::CalculateBoundingVolumeJobPtr::create()) - , m_updateWorldBoundingVolumeJob(Render::UpdateWorldBoundingVolumeJobPtr::create()) - , m_updateTreeEnabledJob(Render::UpdateTreeEnabledJobPtr::create()) - , m_sendRenderCaptureJob(Render::SendRenderCaptureJobPtr::create(this)) - , m_sendBufferCaptureJob(Render::SendBufferCaptureJobPtr::create()) - , m_updateSkinningPaletteJob(Render::UpdateSkinningPaletteJobPtr::create()) - , m_updateLevelOfDetailJob(Render::UpdateLevelOfDetailJobPtr::create()) - , m_updateMeshTriangleListJob(Render::UpdateMeshTriangleListJobPtr::create()) - , m_filterCompatibleTechniqueJob(Render::FilterCompatibleTechniqueJobPtr::create()) - , m_bufferGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyBuffers(); }, JobTypes::DirtyBufferGathering)) - , m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering)) - , m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering)) - , m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering)) - , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading)) - , m_ownedContext(false) - , m_offscreenHelper(nullptr) - #if QT_CONFIG(qt3d_profile_jobs) - , m_commandExecuter(new Qt3DRender::Debug::CommandExecuter(this)) - #endif -{ - // Set renderer as running - it will wait in the context of the - // RenderThread for RenderViews to be submitted - m_running.fetchAndStoreOrdered(1); - if (m_renderThread) - m_renderThread->waitForStart(); - - // Create jobs to update transforms and bounding volumes - // We can only update bounding volumes once all world transforms are known - m_updateWorldBoundingVolumeJob->addDependency(m_worldTransformJob); - m_updateWorldBoundingVolumeJob->addDependency(m_calculateBoundingVolumeJob); - m_expandBoundingVolumeJob->addDependency(m_updateWorldBoundingVolumeJob); - m_updateShaderDataTransformJob->addDependency(m_worldTransformJob); - m_pickBoundingVolumeJob->addDependency(m_expandBoundingVolumeJob); - // m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs - - // Dirty texture gathering depends on m_syncTextureLoadingJob - // m_syncTextureLoadingJob will depend on the texture loading jobs - m_textureGathererJob->addDependency(m_syncTextureLoadingJob); - - // Ensures all skeletons are loaded before we try to update them - m_updateSkinningPaletteJob->addDependency(m_syncTextureLoadingJob); - - // All world stuff depends on the RenderEntity's localBoundingVolume - m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob); - m_pickBoundingVolumeJob->addDependency(m_updateMeshTriangleListJob); - m_rayCastingJob->addDependency(m_updateMeshTriangleListJob); - - m_introspectShaderJob->addDependency(m_filterCompatibleTechniqueJob); - - m_filterCompatibleTechniqueJob->setRenderer(this); - - m_defaultRenderStateSet = new RenderStateSet; - m_defaultRenderStateSet->addState(RenderStateSet::createState<DepthTest>(GL_LESS)); - m_defaultRenderStateSet->addState(RenderStateSet::createState<CullFace>(GL_BACK)); - m_defaultRenderStateSet->addState(RenderStateSet::createState<ColorMask>(true, true, true, true)); -} - -Renderer::~Renderer() -{ - // If using a threaded rendering approach, tell the thread to exit - // and wait for it to be done - m_running.fetchAndStoreOrdered(0); - if (m_renderThread) - m_renderThread->wait(); - - delete m_renderQueue; - delete m_defaultRenderStateSet; - delete m_shaderCache; - - if (!m_ownedContext) - QObject::disconnect(m_contextConnection); -} - -void Renderer::dumpInfo() const -{ - qDebug() << Q_FUNC_INFO << "t =" << m_time; - - const ShaderManager *shaderManager = m_nodesManager->shaderManager(); - qDebug() << "=== Shader Manager ==="; - qDebug() << *shaderManager; - - const TextureManager *textureManager = m_nodesManager->textureManager(); - qDebug() << "=== Texture Manager ==="; - qDebug() << *textureManager; - - const TextureImageManager *textureImageManager = m_nodesManager->textureImageManager(); - qDebug() << "=== Texture Image Manager ==="; - qDebug() << *textureImageManager; -} - -qint64 Renderer::time() const -{ - return m_time; -} - -void Renderer::setTime(qint64 time) -{ - m_time = time; -} - -void Renderer::setNodeManagers(NodeManagers *managers) -{ - m_nodesManager = managers; - - m_updateShaderDataTransformJob->setManagers(m_nodesManager); - m_cleanupJob->setManagers(m_nodesManager); - m_calculateBoundingVolumeJob->setManagers(m_nodesManager); - m_pickBoundingVolumeJob->setManagers(m_nodesManager); - m_rayCastingJob->setManagers(m_nodesManager); - m_updateWorldBoundingVolumeJob->setManager(m_nodesManager->renderNodesManager()); - m_sendRenderCaptureJob->setManagers(m_nodesManager); - m_sendBufferCaptureJob->setManagers(m_nodesManager); - m_updateLevelOfDetailJob->setManagers(m_nodesManager); - m_updateSkinningPaletteJob->setManagers(m_nodesManager); - m_updateMeshTriangleListJob->setManagers(m_nodesManager); - m_filterCompatibleTechniqueJob->setManager(m_nodesManager->techniqueManager()); -} - -void Renderer::setServices(QServiceLocator *services) -{ - m_services = services; - - m_nodesManager->sceneManager()->setDownloadService(m_services->downloadHelperService()); -} - -NodeManagers *Renderer::nodeManagers() const -{ - return m_nodesManager; -} - -/*! - \internal - - Return context which can be used to share resources safely - with qt3d main render context. -*/ -QOpenGLContext *Renderer::shareContext() const -{ - QMutexLocker lock(&m_shareContextMutex); - return m_shareContext ? m_shareContext - : (m_submissionContext->openGLContext() - ? m_submissionContext->openGLContext()->shareContext() - : nullptr); -} - -// Executed in the command thread -void Renderer::loadShader(Shader *shader) const -{ - Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload); - LoadShaderCommand cmd(shader); - m_commandThread->executeCommand(&cmd); -} - -void Renderer::setOpenGLContext(QOpenGLContext *context) -{ - m_glContext = context; -} - -// Called in RenderThread context by the run method of RenderThread -// RenderThread has locked the mutex already and unlocks it when this -// method termintates -void Renderer::initialize() -{ - m_submissionContext.reset(new SubmissionContext); - m_submissionContext->setRenderer(this); - - QOpenGLContext* ctx = m_glContext; - - { - QMutexLocker lock(&m_shareContextMutex); - // If we are using our own context (not provided by QtQuick), - // we need to create it - if (!m_glContext) { - ctx = new QOpenGLContext; - ctx->setShareContext(qt_gl_global_share_context()); - - // TO DO: Shouldn't we use the highest context available and trust - // QOpenGLContext to fall back on the best lowest supported ? - const QByteArray debugLoggingMode = qgetenv("QT3DRENDER_DEBUG_LOGGING"); - - if (!debugLoggingMode.isEmpty()) { - QSurfaceFormat sf = ctx->format(); - sf.setOption(QSurfaceFormat::DebugContext); - ctx->setFormat(sf); - } - - // Create OpenGL context - if (ctx->create()) - qCDebug(Backend) << "OpenGL context created with actual format" << ctx->format(); - else - qCWarning(Backend) << Q_FUNC_INFO << "OpenGL context creation failed"; - m_ownedContext = true; - } else { - // Context is not owned by us, so we need to know if it gets destroyed - m_contextConnection = QObject::connect(m_glContext, &QOpenGLContext::aboutToBeDestroyed, - [this] { releaseGraphicsResources(); }); - } - - if (!ctx->shareContext()) { - m_shareContext = new QOpenGLContext; - m_shareContext->setFormat(ctx->format()); - m_shareContext->setShareContext(ctx); - m_shareContext->create(); - } - - // Set shader cache on submission context and command thread - m_submissionContext->setShaderCache(m_shaderCache); - m_commandThread->setShaderCache(m_shaderCache); - - // Note: we don't have a surface at this point - // The context will be made current later on (at render time) - m_submissionContext->setOpenGLContext(ctx); - - // Store the format used by the context and queue up creating an - // offscreen surface in the main thread so that it is available - // for use when we want to shutdown the renderer. We need to create - // the offscreen surface on the main thread because on some platforms - // (MS Windows), an offscreen surface is just a hidden QWindow. - m_format = ctx->format(); - QMetaObject::invokeMethod(m_offscreenHelper, "createOffscreenSurface"); - - // Initialize command thread (uses the offscreen surface to make its own ctx current) - m_commandThread->initialize(ctx, m_offscreenHelper); - // Note: the offscreen surface is also used at shutdown time to release resources - // of the submission gl context (when the window is already gone). - // By that time (in releaseGraphicResources), the commandThread has been destroyed - // and the offscreenSurface can be reused - } - - // Awake setScenegraphRoot in case it was waiting - m_waitForInitializationToBeCompleted.release(1); - // Allow the aspect manager to proceed - m_vsyncFrameAdvanceService->proceedToNextFrame(); -} - -/*! - * \internal - * - * Signals for the renderer to stop rendering. If a threaded renderer is in use, - * the render thread will call releaseGraphicsResources() just before the thread exits. - * If rendering synchronously, this function will call releaseGraphicsResources(). - */ -void Renderer::shutdown() -{ - qCDebug(Backend) << Q_FUNC_INFO << "Requesting renderer shutdown"; - m_running.store(0); - - // We delete any renderqueue that we may not have had time to render - // before the surface was destroyed - qDeleteAll(m_renderQueue->nextFrameQueue()); - m_renderQueue->reset(); - - m_commandThread->shutdown(); - - if (!m_renderThread) { - releaseGraphicsResources(); - } else { - // Wake up the render thread in case it is waiting for some renderviews - // to be ready. The isReadyToSubmit() function checks for a shutdown - // having been requested. - m_submitRenderViewsSemaphore.release(1); - m_renderThread->wait(); - } -} - -/*! - \internal - - When using a threaded renderer this function is called in the context of the - RenderThread to do any shutdown and cleanup that needs to be performed in the - thread where the OpenGL context lives. - - When using Scene3D or anything that provides a custom QOpenGLContext (not - owned by Qt3D) this function is called whenever the signal - QOpenGLContext::aboutToBeDestroyed is emitted. In that case this function - is called in the context of the emitter's thread. -*/ -void Renderer::releaseGraphicsResources() -{ - // We may get called twice when running inside of a Scene3D. Once when Qt Quick - // wants to shutdown, and again when the render aspect gets unregistered. So - // check that we haven't already cleaned up before going any further. - if (!m_submissionContext) - return; - - // Try to temporarily make the context current so we can free up any resources - QMutexLocker locker(&m_offscreenSurfaceMutex); - QOffscreenSurface *offscreenSurface = m_offscreenHelper->offscreenSurface(); - if (!offscreenSurface) { - qWarning() << "Failed to make context current: OpenGL resources will not be destroyed"; - return; - } - - QOpenGLContext *context = m_submissionContext->openGLContext(); - Q_ASSERT(context); - if (context->makeCurrent(offscreenSurface)) { - - // Clean up the graphics context and any resources - const QVector<GLTexture*> activeTextures = m_nodesManager->glTextureManager()->activeResources(); - for (GLTexture *tex : activeTextures) - tex->destroyGLTexture(); - - // Do the same thing with buffers - const QVector<HGLBuffer> activeBuffers = m_nodesManager->glBufferManager()->activeHandles(); - for (const HGLBuffer &bufferHandle : activeBuffers) { - GLBuffer *buffer = m_nodesManager->glBufferManager()->data(bufferHandle); - buffer->destroy(m_submissionContext.data()); - } - - // Do the same thing with VAOs - const QVector<HVao> activeVaos = m_nodesManager->vaoManager()->activeHandles(); - for (const HVao &vaoHandle : activeVaos) { - OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(vaoHandle); - vao->destroy(); - } - - context->doneCurrent(); - } else { - qWarning() << "Failed to make context current: OpenGL resources will not be destroyed"; - } - - if (m_ownedContext) - delete context; - if (m_shareContext) - delete m_shareContext; - - m_submissionContext.reset(nullptr); - qCDebug(Backend) << Q_FUNC_INFO << "Renderer properly shutdown"; -} - -void Renderer::setSurfaceExposed(bool exposed) -{ - qCDebug(Backend) << "Window exposed: " << exposed; - m_exposed.fetchAndStoreOrdered(exposed); -} - -Render::FrameGraphNode *Renderer::frameGraphRoot() const -{ - Q_ASSERT(m_settings); - if (m_nodesManager && m_nodesManager->frameGraphManager() && m_settings) - return m_nodesManager->frameGraphManager()->lookupNode(m_settings->activeFrameGraphID()); - return nullptr; -} - -// QAspectThread context -// Order of execution : -// 1) RenderThread is created -> release 1 of m_waitForInitializationToBeCompleted when started -// 2) setSceneRoot waits to acquire initialization -// 3) submitRenderView -> check for surface -// -> make surface current + create proper glHelper if needed -void Renderer::setSceneRoot(QBackendNodeFactory *factory, Entity *sgRoot) -{ - Q_ASSERT(sgRoot); - Q_UNUSED(factory); - - // If initialization hasn't been completed we must wait - m_waitForInitializationToBeCompleted.acquire(); - - m_renderSceneRoot = sgRoot; - if (!m_renderSceneRoot) - qCWarning(Backend) << "Failed to build render scene"; - m_renderSceneRoot->dump(); - qCDebug(Backend) << Q_FUNC_INFO << "DUMPING SCENE"; - - // Set the scene root on the jobs - m_worldTransformJob->setRoot(m_renderSceneRoot); - m_expandBoundingVolumeJob->setRoot(m_renderSceneRoot); - m_calculateBoundingVolumeJob->setRoot(m_renderSceneRoot); - m_cleanupJob->setRoot(m_renderSceneRoot); - m_pickBoundingVolumeJob->setRoot(m_renderSceneRoot); - m_rayCastingJob->setRoot(m_renderSceneRoot); - m_updateLevelOfDetailJob->setRoot(m_renderSceneRoot); - m_updateSkinningPaletteJob->setRoot(m_renderSceneRoot); - m_updateTreeEnabledJob->setRoot(m_renderSceneRoot); - - // Set all flags to dirty - m_dirtyBits.marked |= AbstractRenderer::AllDirty; -} - -void Renderer::registerEventFilter(QEventFilterService *service) -{ - qCDebug(Backend) << Q_FUNC_INFO << QThread::currentThread(); - service->registerEventFilter(m_pickEventFilter.data(), 1024); -} - -void Renderer::setSettings(RenderSettings *settings) -{ - m_settings = settings; -} - -RenderSettings *Renderer::settings() const -{ - return m_settings; -} - -void Renderer::render() -{ - // Traversing the framegraph tree from root to lead node - // Allows us to define the rendering set up - // Camera, RenderTarget ... - - // Utimately the renderer should be a framework - // For the processing of the list of renderviews - - // Matrice update, bounding volumes computation ... - // Should be jobs - - // namespace Qt3DCore has 2 distincts node trees - // One scene description - // One framegraph description - - while (m_running.load() > 0) { - doRender(); - // TO DO: Restore windows exposed detection - // Probably needs to happens some place else though - } -} - -void Renderer::doRender(bool scene3dBlocking) -{ - Renderer::ViewSubmissionResultData submissionData; - bool hasCleanedQueueAndProceeded = false; - bool preprocessingComplete = false; - bool beganDrawing = false; - const bool canSubmit = isReadyToSubmit(); - - // Lock the mutex to protect access to the renderQueue while we look for its state - QMutexLocker locker(m_renderQueue->mutex()); - bool queueIsComplete = m_renderQueue->isFrameQueueComplete(); - const bool queueIsEmpty = m_renderQueue->targetRenderViewCount() == 0; - - // Scene3D Blocking Mode - if (scene3dBlocking && !queueIsComplete && !queueIsEmpty) { - int i = 0; - // We wait at most 10ms to avoid a case we could never recover from - while (!queueIsComplete && i++ < 10) { - QThread::msleep(1); - qCDebug(Backend) << Q_FUNC_INFO << "Waiting for ready queue (try:" << i << "/ 10)"; - locker.unlock(); - queueIsComplete = m_renderQueue->isFrameQueueComplete(); - locker.relock(); - } - } - - // When using synchronous rendering (QtQuick) - // We are not sure that the frame queue is actually complete - // Since a call to render may not be synched with the completions - // of the RenderViewJobs - // In such a case we return early, waiting for a next call with - // the frame queue complete at this point - - // RenderQueue is complete (but that means it may be of size 0) - if (canSubmit && (queueIsComplete && !queueIsEmpty)) { - const QVector<Render::RenderView *> renderViews = m_renderQueue->nextFrameQueue(); - -#if QT_CONFIG(qt3d_profile_jobs) - // Save start of frame - JobRunStats submissionStatsPart1; - JobRunStats submissionStatsPart2; - submissionStatsPart1.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart1; - submissionStatsPart1.jobId.typeAndInstance[1] = 0; - submissionStatsPart1.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); - submissionStatsPart1.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - submissionStatsPart2.jobId.typeAndInstance[0] = JobTypes::FrameSubmissionPart2; - submissionStatsPart2.jobId.typeAndInstance[1] = 0; - submissionStatsPart2.threadId = reinterpret_cast<quint64>(QThread::currentThreadId()); -#endif - - if (canRender()) { - { // Scoped to destroy surfaceLock - QSurface *surface = nullptr; - for (const Render::RenderView *rv: renderViews) { - surface = rv->surface(); - if (surface) - break; - } - - SurfaceLocker surfaceLock(surface); - const bool surfaceIsValid = (surface && surfaceLock.isSurfaceValid()); - if (surfaceIsValid) { - // Reset state for each draw if we don't have complete control of the context - if (!m_ownedContext) - m_submissionContext->setCurrentStateSet(nullptr); - beganDrawing = m_submissionContext->beginDrawing(surface); - if (beganDrawing) { - // 1) Execute commands for buffer uploads, texture updates, shader loading first - updateGLResources(); - // 2) Update VAO and copy data into commands to allow concurrent submission - prepareCommandsSubmission(renderViews); - preprocessingComplete = true; - } - } - } - // 2) Proceed to next frame and start preparing frame n + 1 - m_renderQueue->reset(); - locker.unlock(); // Done protecting RenderQueue - m_vsyncFrameAdvanceService->proceedToNextFrame(); - hasCleanedQueueAndProceeded = true; - -#if QT_CONFIG(qt3d_profile_jobs) - if (preprocessingComplete) { - submissionStatsPart2.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - submissionStatsPart1.endTime = submissionStatsPart2.startTime; - } -#endif - // Only try to submit the RenderViews if the preprocessing was successful - // This part of the submission is happening in parallel to the RV building for the next frame - if (preprocessingComplete) { - // 3) Submit the render commands for frame n (making sure we never reference something that could be changing) - // Render using current device state and renderer configuration - submissionData = submitRenderViews(renderViews); - - // Perform any required cleanup of the Graphics resources (Buffers deleted, Shader deleted...) - cleanGraphicsResources(); - } - } - -#if QT_CONFIG(qt3d_profile_jobs) - // Execute the pending shell commands - m_commandExecuter->performAsynchronousCommandExecution(renderViews); -#endif - - // Delete all the RenderViews which will clear the allocators - // that were used for their allocation - qDeleteAll(renderViews); - -#if QT_CONFIG(qt3d_profile_jobs) - if (preprocessingComplete) { - // Save submission elapsed time - submissionStatsPart2.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed(); - // Note this is safe since proceedToNextFrame is the one going to trigger - // the write to the file, and this is performed after this step - Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart1); - Qt3DCore::QThreadPooler::addSubmissionLogStatsEntry(submissionStatsPart2); - Profiling::GLTimeRecorder::writeResults(); - } -#endif - } - - // Only reset renderQueue and proceed to next frame if the submission - // succeeded or if we are using a render thread and that is wasn't performed - // already - - // If hasCleanedQueueAndProceeded isn't true this implies that something went wrong - // with the rendering and/or the renderqueue is incomplete from some reason - // (in the case of scene3d the render jobs may be taking too long ....) - // or alternatively it could be complete but empty (RenderQueue of size 0) - if (!hasCleanedQueueAndProceeded && - (m_renderThread || queueIsComplete || queueIsEmpty)) { - // RenderQueue was full but something bad happened when - // trying to render it and therefore proceedToNextFrame was not called - // Note: in this case the renderQueue mutex is still locked - - // Reset the m_renderQueue so that we won't try to render - // with a queue used by a previous frame with corrupted content - // if the current queue was correctly submitted - m_renderQueue->reset(); - - // We allow the RenderTickClock service to proceed to the next frame - // In turn this will allow the aspect manager to request a new set of jobs - // to be performed for each aspect - m_vsyncFrameAdvanceService->proceedToNextFrame(); - } - - // Perform the last swapBuffers calls after the proceedToNextFrame - // as this allows us to gain a bit of time for the preparation of the - // next frame - // Finish up with last surface used in the list of RenderViews - if (beganDrawing) { - SurfaceLocker surfaceLock(submissionData.surface); - // Finish up with last surface used in the list of RenderViews - m_submissionContext->endDrawing(submissionData.lastBoundFBOId == m_submissionContext->defaultFBO() && surfaceLock.isSurfaceValid()); - } -} - -// Called by RenderViewJobs -// When the frameQueue is complete and we are using a renderThread -// we allow the render thread to proceed -void Renderer::enqueueRenderView(Render::RenderView *renderView, int submitOrder) -{ - QMutexLocker locker(m_renderQueue->mutex()); // Prevent out of order execution - // We cannot use a lock free primitive here because: - // - QVector is not thread safe - // - Even if the insert is made correctly, the isFrameComplete call - // could be invalid since depending on the order of execution - // the counter could be complete but the renderview not yet added to the - // buffer depending on whichever order the cpu decides to process this - const bool isQueueComplete = m_renderQueue->queueRenderView(renderView, submitOrder); - locker.unlock(); // We're done protecting the queue at this point - if (isQueueComplete) { - if (m_renderThread && m_running.load()) - Q_ASSERT(m_submitRenderViewsSemaphore.available() == 0); - m_submitRenderViewsSemaphore.release(1); - } -} - -bool Renderer::canRender() const -{ - // Make sure that we've not been told to terminate - if (m_renderThread && !m_running.load()) { - qCDebug(Rendering) << "RenderThread termination requested whilst waiting"; - return false; - } - - // TO DO: Check if all surfaces have been destroyed... - // It may be better if the last window to be closed trigger a call to shutdown - // Rather than having checks for the surface everywhere - - return true; -} - -bool Renderer::isReadyToSubmit() -{ - // If we are using a render thread, make sure that - // we've been told to render before rendering - if (m_renderThread) { // Prevent ouf of order execution - m_submitRenderViewsSemaphore.acquire(1); - - // Check if shutdown has been requested - if (m_running.load() == 0) - return false; - - // When using Thread rendering, the semaphore should only - // be released when the frame queue is complete and there's - // something to render - // The case of shutdown should have been handled just before - Q_ASSERT(m_renderQueue->isFrameQueueComplete()); - } - return true; -} - -// Main thread -QVariant Renderer::executeCommand(const QStringList &args) -{ -#if QT_CONFIG(qt3d_profile_jobs) - return m_commandExecuter->executeCommand(args); -#else - Q_UNUSED(args); -#endif - return QVariant(); -} - -/*! - \internal - Called in the context of the aspect thread from QRenderAspect::onRegistered -*/ -void Renderer::setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) -{ - QMutexLocker locker(&m_offscreenSurfaceMutex); - m_offscreenHelper = helper; -} - -QSurfaceFormat Renderer::format() -{ - return m_format; -} - -// When this function is called, we must not be processing the commands for frame n+1 -void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderViews) -{ - OpenGLVertexArrayObject *vao = nullptr; - QHash<HVao, bool> updatedTable; - - for (RenderView *rv: renderViews) { - const QVector<RenderCommand *> commands = rv->commands(); - for (RenderCommand *command : commands) { - // Update/Create VAO - if (command->m_type == RenderCommand::Draw) { - Geometry *rGeometry = m_nodesManager->data<Geometry, GeometryManager>(command->m_geometry); - GeometryRenderer *rGeometryRenderer = m_nodesManager->data<GeometryRenderer, GeometryRendererManager>(command->m_geometryRenderer); - Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader); - - // We should never have inserted a command for which these are null - // in the first place - Q_ASSERT(rGeometry && rGeometryRenderer && shader); - - // The VAO should be created only once for a QGeometry and a ShaderProgram - // Manager should have a VAO Manager that are indexed by QMeshData and Shader - // RenderCommand should have a handle to the corresponding VAO for the Mesh and Shader - HVao vaoHandle; - - // Create VAO or return already created instance associated with command shader/geometry - // (VAO is emulated if not supported) - createOrUpdateVAO(command, &vaoHandle, &vao); - command->m_vao = vaoHandle; - - // Avoids redoing the same thing for the same VAO - if (!updatedTable.contains(vaoHandle)) { - updatedTable.insert(vaoHandle, true); - - // Do we have any attributes that are dirty ? - const bool requiresPartialVAOUpdate = requiresVAOAttributeUpdate(rGeometry, command); - - // If true, we need to reupload all attributes to set the VAO - // Otherwise only dirty attributes will be updates - const bool requiresFullVAOUpdate = (!vao->isSpecified()) || (rGeometry->isDirty() || rGeometryRenderer->isDirty()); - - // Append dirty Geometry to temporary vector - // so that its dirtiness can be unset later - if (rGeometry->isDirty()) - m_dirtyGeometry.push_back(rGeometry); - - if (!command->m_attributes.isEmpty() && (requiresFullVAOUpdate || requiresPartialVAOUpdate)) { - Profiling::GLTimeRecorder recorder(Profiling::VAOUpload); - // Activate shader - m_submissionContext->activateShader(shader->dna()); - // Bind VAO - vao->bind(); - // Update or set Attributes and Buffers for the given rGeometry and Command - // Note: this fills m_dirtyAttributes as well - if (updateVAOWithAttributes(rGeometry, command, shader, requiresFullVAOUpdate)) - vao->setSpecified(true); - } - } - - // Unset dirtiness on rGeometryRenderer only - // The rGeometry may be shared by several rGeometryRenderer - // so we cannot unset its dirtiness at this point - if (rGeometryRenderer->isDirty()) - rGeometryRenderer->unsetDirty(); - - // Prepare the ShaderParameterPack based on the active uniforms of the shader - shader->prepareUniforms(command->m_parameterPack); - - // TO DO: The step below could be performed by the RenderCommand builder job - { // Scoped to show extent - command->m_isValid = !command->m_attributes.empty(); - if (!command->m_isValid) - continue; - - // Update the draw command with what's going to be needed for the drawing - uint primitiveCount = rGeometryRenderer->vertexCount(); - uint estimatedCount = 0; - Attribute *indexAttribute = nullptr; - Attribute *indirectAttribute = nullptr; - - const QVector<Qt3DCore::QNodeId> attributeIds = rGeometry->attributes(); - for (Qt3DCore::QNodeId attributeId : attributeIds) { - Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); - switch (attribute->attributeType()) { - case QAttribute::IndexAttribute: - indexAttribute = attribute; - break; - case QAttribute::DrawIndirectAttribute: - indirectAttribute = attribute; - break; - case QAttribute::VertexAttribute: { - if (command->m_attributes.contains(attribute->nameId())) - estimatedCount = qMax(attribute->count(), estimatedCount); - break; - } - default: - Q_UNREACHABLE(); - break; - } - } - - command->m_drawIndexed = (indexAttribute != nullptr); - command->m_drawIndirect = (indirectAttribute != nullptr); - - // Update the draw command with all the information required for the drawing - if (command->m_drawIndexed) { - command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType()); - command->m_indexAttributeByteOffset = indexAttribute->byteOffset() + rGeometryRenderer->indexBufferByteOffset(); - } - - // Note: we only care about the primitiveCount when using direct draw calls - // For indirect draw calls it is assumed the buffer was properly set already - if (command->m_drawIndirect) { - command->m_indirectAttributeByteOffset = indirectAttribute->byteOffset(); - command->m_indirectDrawBuffer = m_nodesManager->bufferManager()->lookupHandle(indirectAttribute->bufferId()); - } else { - // Use the count specified by the GeometryRender - // If not specify use the indexAttribute count if present - // Otherwise tries to use the count from the attribute with the highest count - if (primitiveCount == 0) { - if (indexAttribute) - primitiveCount = indexAttribute->count(); - else - primitiveCount = estimatedCount; - } - } - - command->m_primitiveCount = primitiveCount; - command->m_primitiveType = rGeometryRenderer->primitiveType(); - command->m_primitiveRestartEnabled = rGeometryRenderer->primitiveRestartEnabled(); - command->m_restartIndexValue = rGeometryRenderer->restartIndexValue(); - command->m_firstInstance = rGeometryRenderer->firstInstance(); - command->m_instanceCount = rGeometryRenderer->instanceCount(); - command->m_firstVertex = rGeometryRenderer->firstVertex(); - command->m_indexOffset = rGeometryRenderer->indexOffset(); - command->m_verticesPerPatch = rGeometryRenderer->verticesPerPatch(); - } // scope - } else if (command->m_type == RenderCommand::Compute) { - Shader *shader = m_nodesManager->data<Shader, ShaderManager>(command->m_shader); - Q_ASSERT(shader); - - // Prepare the ShaderParameterPack based on the active uniforms of the shader - shader->prepareUniforms(command->m_parameterPack); - } - } - } - - // Make sure we leave nothing bound - if (vao) - vao->release(); - - // Unset dirtiness on Geometry and Attributes - // Note: we cannot do it in the loop above as we want to be sure that all - // the VAO which reference the geometry/attributes are properly updated - for (Attribute *attribute : qAsConst(m_dirtyAttributes)) - attribute->unsetDirty(); - m_dirtyAttributes.clear(); - - for (Geometry *geometry : qAsConst(m_dirtyGeometry)) - geometry->unsetDirty(); - m_dirtyGeometry.clear(); -} - -// Executed in a job -void Renderer::lookForAbandonedVaos() -{ - const QVector<HVao> activeVaos = m_nodesManager->vaoManager()->activeHandles(); - for (const HVao &handle : activeVaos) { - OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(handle); - - // Make sure to only mark VAOs for deletion that were already created - // (ignore those that might be currently under construction in the render thread) - if (vao && vao->isAbandoned(m_nodesManager->geometryManager(), m_nodesManager->shaderManager())) { - m_abandonedVaosMutex.lock(); - m_abandonedVaos.push_back(handle); - m_abandonedVaosMutex.unlock(); - } - } -} - -// Executed in a job -void Renderer::lookForDirtyBuffers() -{ - const QVector<HBuffer> activeBufferHandles = m_nodesManager->bufferManager()->activeHandles(); - for (const HBuffer &handle: activeBufferHandles) { - Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - if (buffer->isDirty()) - m_dirtyBuffers.push_back(handle); - } -} - -void Renderer::lookForDownloadableBuffers() -{ - m_downloadableBuffers.clear(); - const QVector<HBuffer> activeBufferHandles = m_nodesManager->bufferManager()->activeHandles(); - for (const HBuffer &handle : activeBufferHandles) { - Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - if (buffer->access() & QBuffer::Read) - m_downloadableBuffers.push_back(handle); - } -} - -// Executed in a job -void Renderer::lookForDirtyTextures() -{ - const QVector<HTexture> activeTextureHandles = m_nodesManager->textureManager()->activeHandles(); - for (const HTexture &handle: activeTextureHandles) { - Texture *texture = m_nodesManager->textureManager()->data(handle); - // Dirty meaning that something has changed on the texture - // either properties, parameters, generator or a texture image - if (texture->dirtyFlags() != Texture::NotDirty) - m_dirtyTextures.push_back(handle); - } -} - -// Executed in a job -void Renderer::reloadDirtyShaders() -{ - Q_ASSERT(isRunning()); - const QVector<HTechnique> activeTechniques = m_nodesManager->techniqueManager()->activeHandles(); - const QVector<HShaderBuilder> activeBuilders = m_nodesManager->shaderBuilderManager()->activeHandles(); - for (const HTechnique &techniqueHandle : activeTechniques) { - Technique *technique = m_nodesManager->techniqueManager()->data(techniqueHandle); - // If api of the renderer matches the one from the technique - if (technique->isCompatibleWithRenderer()) { - const auto passIds = technique->renderPasses(); - for (const QNodeId passId : passIds) { - RenderPass *renderPass = m_nodesManager->renderPassManager()->lookupResource(passId); - HShader shaderHandle = m_nodesManager->shaderManager()->lookupHandle(renderPass->shaderProgram()); - Shader *shader = m_nodesManager->shaderManager()->data(shaderHandle); - - ShaderBuilder *shaderBuilder = nullptr; - for (const HShaderBuilder &builderHandle : activeBuilders) { - ShaderBuilder *builder = m_nodesManager->shaderBuilderManager()->data(builderHandle); - if (builder->shaderProgramId() == shader->peerId()) { - shaderBuilder = builder; - break; - } - } - - if (shaderBuilder) { - shaderBuilder->setGraphicsApi(*technique->graphicsApiFilter()); - - for (int i = 0; i <= ShaderBuilder::Compute; i++) { - const auto builderType = static_cast<ShaderBuilder::ShaderType>(i); - if (!shaderBuilder->shaderGraph(builderType).isValid()) - continue; - - if (shaderBuilder->isShaderCodeDirty(builderType)) { - shaderBuilder->generateCode(builderType); - } - - QShaderProgram::ShaderType shaderType = QShaderProgram::Vertex; - switch (builderType) { - case ShaderBuilder::Vertex: - shaderType = QShaderProgram::Vertex; - break; - case ShaderBuilder::TessellationControl: - shaderType = QShaderProgram::TessellationControl; - break; - case ShaderBuilder::TessellationEvaluation: - shaderType = QShaderProgram::TessellationEvaluation; - break; - case ShaderBuilder::Geometry: - shaderType = QShaderProgram::Geometry; - break; - case ShaderBuilder::Fragment: - shaderType = QShaderProgram::Fragment; - break; - case ShaderBuilder::Compute: - shaderType = QShaderProgram::Compute; - break; - } - - const auto code = shaderBuilder->shaderCode(builderType); - shader->setShaderCode(shaderType, code); - } - } - - if (Q_UNLIKELY(shader->hasPendingNotifications())) - shader->submitPendingNotifications(); - // If the shader hasn't be loaded, load it - if (shader != nullptr && !shader->isLoaded()) - loadShader(shader); - } - } - } -} - -// Render Thread -void Renderer::updateGLResources() -{ - { - Profiling::GLTimeRecorder recorder(Profiling::BufferUpload); - const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers); - for (const HBuffer &handle: dirtyBufferHandles) { - Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - // Forces creation if it doesn't exit - // Also note the binding point doesn't really matter here, we just upload data - if (!m_submissionContext->hasGLBufferForBuffer(buffer)) - m_submissionContext->glBufferForRenderBuffer(buffer, GLBuffer::ArrayBuffer); - // Update the glBuffer data - m_submissionContext->updateBuffer(buffer); - buffer->unsetDirty(); - } - } - - { - Profiling::GLTimeRecorder recorder(Profiling::TextureUpload); - const QVector<HTexture> activeTextureHandles = std::move(m_dirtyTextures); - for (const HTexture &handle: activeTextureHandles) { - Texture *texture = m_nodesManager->textureManager()->data(handle); - // Upload/Update texture - updateTexture(texture); - } - } - // When Textures are cleaned up, their id is saved - // so that they can be cleaned up in the render thread - // Note: we perform this step in second so that the previous updateTexture call - // has a chance to find a shared texture - const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = m_nodesManager->textureManager()->takeTexturesIdsToCleanup(); - for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds) { - cleanupTexture(m_nodesManager->textureManager()->lookupResource(textureCleanedUpId)); - // We can really release the texture at this point - m_nodesManager->textureManager()->releaseResource(textureCleanedUpId); - } -} - -// Render Thread -void Renderer::updateTexture(Texture *texture) -{ - // Check that the current texture images are still in place, if not, do not update - const bool isValid = texture->isValid(); - if (!isValid) - return; - - // For implementing unique, non-shared, non-cached textures. - // for now, every texture is shared by default - - bool isUnique = false; - - // TO DO: Update the vector once per frame (or in a job) - const QVector<HAttachment> activeRenderTargetOutputs = m_nodesManager->attachmentManager()->activeHandles(); - // A texture is unique if it's being reference by a render target output - for (const HAttachment &attachmentHandle : activeRenderTargetOutputs) { - RenderTargetOutput *attachment = m_nodesManager->attachmentManager()->data(attachmentHandle); - if (attachment->textureUuid() == texture->peerId()) { - isUnique = true; - break; - } - } - - // Try to find the associated GLTexture for the backend Texture - GLTextureManager *glTextureManager = m_nodesManager->glTextureManager(); - GLTexture *glTexture = glTextureManager->lookupResource(texture->peerId()); - - // No GLTexture associated yet -> create it - if (glTexture == nullptr) { - if (isUnique) - glTextureManager->createUnique(texture); - else - glTextureManager->getOrCreateShared(texture); - texture->unsetDirty(); - return; - } - - // if this texture is a shared texture, we might need to look for a new TextureImpl - // and abandon the old one - if (glTextureManager->isShared(glTexture)) { - glTextureManager->abandon(glTexture, texture); - // Check if a shared texture should become unique - if (isUnique) - glTextureManager->createUnique(texture); - else - glTextureManager->getOrCreateShared(texture); - texture->unsetDirty(); - return; - } - - // this texture node is the only one referring to the GLTexture. - // we could thus directly modify the texture. Instead, for non-unique textures, - // we first see if there is already a matching texture present. - if (!isUnique) { - GLTexture *newSharedTex = glTextureManager->findMatchingShared(texture); - if (newSharedTex && newSharedTex != glTexture) { - glTextureManager->abandon(glTexture, texture); - glTextureManager->adoptShared(newSharedTex, texture); - texture->unsetDirty(); - return; - } - } - - // we hold a reference to a unique or exclusive access to a shared texture - // we can thus modify the texture directly. - const Texture::DirtyFlags dirtyFlags = texture->dirtyFlags(); - - if (dirtyFlags.testFlag(Texture::DirtyProperties) && - !glTextureManager->setProperties(glTexture, texture->properties())) - qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setProperties failed, should be non-shared"; - - if (dirtyFlags.testFlag(Texture::DirtyParameters) && - !glTextureManager->setParameters(glTexture, texture->parameters())) - qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setParameters failed, should be non-shared"; - - // Will make the texture requestUpload - if (dirtyFlags.testFlag(Texture::DirtyImageGenerators) && - !glTextureManager->setImages(glTexture, texture->textureImages())) - qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerators failed, should be non-shared"; - - // Will make the texture requestUpload - if (dirtyFlags.testFlag(Texture::DirtyDataGenerator) && - !glTextureManager->setGenerator(glTexture, texture->dataGenerator())) - qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerator failed, should be non-shared"; - - // Unset the dirty flag on the texture - texture->unsetDirty(); -} - -// Render Thread -void Renderer::cleanupTexture(const Texture *texture) -{ - GLTextureManager *glTextureManager = m_nodesManager->glTextureManager(); - GLTexture *glTexture = glTextureManager->lookupResource(texture->peerId()); - - if (glTexture != nullptr) - glTextureManager->abandon(glTexture, texture); -} - -void Renderer::downloadGLBuffers() -{ - lookForDownloadableBuffers(); - const QVector<HBuffer> downloadableHandles = std::move(m_downloadableBuffers); - for (const HBuffer &handle : downloadableHandles) { - Buffer *buffer = m_nodesManager->bufferManager()->data(handle); - QByteArray content = m_submissionContext->downloadBufferContent(buffer); - m_sendBufferCaptureJob->addRequest(QPair<Buffer*, QByteArray>(buffer, content)); - } -} - -// Happens in RenderThread context when all RenderViewJobs are done -// Returns the id of the last bound FBO -Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Render::RenderView *> &renderViews) -{ - QElapsedTimer timer; - quint64 queueElapsed = 0; - timer.start(); - - const int renderViewsCount = renderViews.size(); - quint64 frameElapsed = queueElapsed; - m_lastFrameCorrect.store(1); // everything fine until now..... - - qCDebug(Memory) << Q_FUNC_INFO << "rendering frame "; - - // We might not want to render on the default FBO - uint lastBoundFBOId = m_submissionContext->boundFrameBufferObject(); - QSurface *surface = nullptr; - QSurface *previousSurface = nullptr; - for (const Render::RenderView *rv: renderViews) { - previousSurface = rv->surface(); - if (previousSurface) - break; - } - QSurface *lastUsedSurface = nullptr; - - for (int i = 0; i < renderViewsCount; ++i) { - // Initialize GraphicsContext for drawing - // If the RenderView has a RenderStateSet defined - const RenderView *renderView = renderViews.at(i); - - // Check if using the same surface as the previous RenderView. - // If not, we have to free up the context from the previous surface - // and make the context current on the new surface - surface = renderView->surface(); - SurfaceLocker surfaceLock(surface); - - // TO DO: Make sure that the surface we are rendering too has not been unset - - // For now, if we do not have a surface, skip this renderview - // TODO: Investigate if it's worth providing a fallback offscreen surface - // to use when surface is null. Or if we should instead expose an - // offscreensurface to Qt3D. - if (!surface || !surfaceLock.isSurfaceValid()) { - m_lastFrameCorrect.store(0); - continue; - } - - lastUsedSurface = surface; - const bool surfaceHasChanged = surface != previousSurface; - - if (surfaceHasChanged && previousSurface) { - const bool swapBuffers = (lastBoundFBOId == m_submissionContext->defaultFBO()) && PlatformSurfaceFilter::isSurfaceValid(previousSurface); - // We only call swap buffer if we are sure the previous surface is still valid - m_submissionContext->endDrawing(swapBuffers); - } - - if (surfaceHasChanged) { - // If we can't make the context current on the surface, skip to the - // next RenderView. We won't get the full frame but we may get something - if (!m_submissionContext->beginDrawing(surface)) { - qWarning() << "Failed to make OpenGL context current on surface"; - m_lastFrameCorrect.store(0); - continue; - } - - previousSurface = surface; - lastBoundFBOId = m_submissionContext->boundFrameBufferObject(); - } - - // Apply Memory Barrier if needed - if (renderView->memoryBarrier() != QMemoryBarrier::None) - m_submissionContext->memoryBarrier(renderView->memoryBarrier()); - - // Note: the RenderStateSet is allocated once per RV if needed - // and it contains a list of StateVariant value types - RenderStateSet *renderViewStateSet = renderView->stateSet(); - - { - Profiling::GLTimeRecorder recorder(Profiling::StateUpdate); - // Set the RV state if not null, - if (renderViewStateSet != nullptr) - m_submissionContext->setCurrentStateSet(renderViewStateSet); - else - m_submissionContext->setCurrentStateSet(m_defaultRenderStateSet); - } - - // Set RenderTarget ... - // Activate RenderTarget - { - Profiling::GLTimeRecorder recorder(Profiling::RenderTargetUpdate); - m_submissionContext->activateRenderTarget(renderView->renderTargetId(), - renderView->attachmentPack(), - lastBoundFBOId); - } - - { - Profiling::GLTimeRecorder recorder(Profiling::ClearBuffer); - // set color, depth, stencil clear values (only if needed) - auto clearBufferTypes = renderView->clearTypes(); - if (clearBufferTypes & QClearBuffers::ColorBuffer) { - const QVector4D vCol = renderView->globalClearColorBufferInfo().clearColor; - m_submissionContext->clearColor(QColor::fromRgbF(vCol.x(), vCol.y(), vCol.z(), vCol.w())); - } - if (clearBufferTypes & QClearBuffers::DepthBuffer) - m_submissionContext->clearDepthValue(renderView->clearDepthValue()); - if (clearBufferTypes & QClearBuffers::StencilBuffer) - m_submissionContext->clearStencilValue(renderView->clearStencilValue()); - - // Clear BackBuffer - m_submissionContext->clearBackBuffer(clearBufferTypes); - - // if there are ClearColors set for different draw buffers, - // clear each of these draw buffers individually now - const QVector<ClearBufferInfo> clearDrawBuffers = renderView->specificClearColorBufferInfo(); - for (const ClearBufferInfo &clearBuffer : clearDrawBuffers) - m_submissionContext->clearBufferf(clearBuffer.drawBufferIndex, clearBuffer.clearColor); - } - - // Set the Viewport - m_submissionContext->setViewport(renderView->viewport(), renderView->surfaceSize() * renderView->devicePixelRatio()); - - // Execute the render commands - if (!executeCommandsSubmission(renderView)) - m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame! - - // executeCommandsSubmission takes care of restoring the stateset to the value - // of gc->currentContext() at the moment it was called (either - // renderViewStateSet or m_defaultRenderStateSet) - if (!renderView->renderCaptureNodeId().isNull()) { - const QRenderCaptureRequest request = renderView->renderCaptureRequest(); - const QSize size = m_submissionContext->renderTargetSize(renderView->surfaceSize() * renderView->devicePixelRatio()); - QRect rect(QPoint(0, 0), size); - if (!request.rect.isEmpty()) - rect = rect.intersected(request.rect); - QImage image; - if (!rect.isEmpty()) { - // Bind fbo as read framebuffer - m_submissionContext->bindFramebuffer(m_submissionContext->activeFBO(), GraphicsHelperInterface::FBORead); - image = m_submissionContext->readFramebuffer(rect); - } else { - qWarning() << "Requested capture rectangle is outside framebuffer"; - } - Render::RenderCapture *renderCapture = - static_cast<Render::RenderCapture*>(m_nodesManager->frameGraphManager()->lookupNode(renderView->renderCaptureNodeId())); - renderCapture->addRenderCapture(request.captureId, image); - addRenderCaptureSendRequest(renderView->renderCaptureNodeId()); - } - - if (renderView->isDownloadBuffersEnable()) - downloadGLBuffers(); - - // Perform BlitFramebuffer operations - if (renderView->hasBlitFramebufferInfo()) { - const auto &blitFramebufferInfo = renderView->blitFrameBufferInfo(); - const QNodeId inputTargetId = blitFramebufferInfo.sourceRenderTargetId; - const QNodeId outputTargetId = blitFramebufferInfo.destinationRenderTargetId; - const QRect inputRect = blitFramebufferInfo.sourceRect; - const QRect outputRect = blitFramebufferInfo.destinationRect; - const QRenderTargetOutput::AttachmentPoint inputAttachmentPoint = blitFramebufferInfo.sourceAttachmentPoint; - const QRenderTargetOutput::AttachmentPoint outputAttachmentPoint = blitFramebufferInfo.destinationAttachmentPoint; - const QBlitFramebuffer::InterpolationMethod interpolationMethod = blitFramebufferInfo.interpolationMethod; - m_submissionContext->blitFramebuffer(inputTargetId, outputTargetId, inputRect, outputRect, lastBoundFBOId, - inputAttachmentPoint, outputAttachmentPoint, - interpolationMethod); - } - - - frameElapsed = timer.elapsed() - frameElapsed; - qCDebug(Rendering) << Q_FUNC_INFO << "Submitted Renderview " << i + 1 << "/" << renderViewsCount << "in " << frameElapsed << "ms"; - frameElapsed = timer.elapsed(); - } - - // Bind lastBoundFBOId back. Needed also in threaded mode. - // lastBoundFBOId != m_graphicsContext->activeFBO() when the last FrameGraph leaf node/renderView - // contains RenderTargetSelector/RenderTarget - if (lastBoundFBOId != m_submissionContext->activeFBO()) - m_submissionContext->bindFramebuffer(lastBoundFBOId, GraphicsHelperInterface::FBOReadAndDraw); - - // Reset state and call doneCurrent if the surface - // is valid and was actually activated - if (surface && m_submissionContext->hasValidGLHelper()) { - // Reset state to the default state if the last stateset is not the - // defaultRenderStateSet - if (m_submissionContext->currentStateSet() != m_defaultRenderStateSet) - m_submissionContext->setCurrentStateSet(m_defaultRenderStateSet); - } - - queueElapsed = timer.elapsed() - queueElapsed; - qCDebug(Rendering) << Q_FUNC_INFO << "Submission of Queue in " << queueElapsed << "ms <=> " << queueElapsed / renderViewsCount << "ms per RenderView <=> Avg " << 1000.0f / (queueElapsed * 1.0f/ renderViewsCount * 1.0f) << " RenderView/s"; - qCDebug(Rendering) << Q_FUNC_INFO << "Submission Completed in " << timer.elapsed() << "ms"; - - // Stores the necessary information to safely perform - // the last swap buffer call - ViewSubmissionResultData resultData; - resultData.lastBoundFBOId = lastBoundFBOId; - resultData.surface = lastUsedSurface; - - return resultData; -} - -void Renderer::markDirty(BackendNodeDirtySet changes, BackendNode *node) -{ - Q_UNUSED(node); - m_dirtyBits.marked |= changes; -} - -Renderer::BackendNodeDirtySet Renderer::dirtyBits() -{ - return m_dirtyBits.marked; -} - -#if defined(QT_BUILD_INTERNAL) -void Renderer::clearDirtyBits(BackendNodeDirtySet changes) -{ - m_dirtyBits.remaining &= ~changes; - m_dirtyBits.marked &= ~changes; -} -#endif - -bool Renderer::shouldRender() -{ - // Only render if something changed during the last frame, or the last frame - // was not rendered successfully (or render-on-demand is disabled) - return (m_settings->renderPolicy() == QRenderSettings::Always - || m_dirtyBits.marked != 0 - || m_dirtyBits.remaining != 0 - || !m_lastFrameCorrect.load()); -} - -void Renderer::skipNextFrame() -{ - Q_ASSERT(m_settings->renderPolicy() != QRenderSettings::Always); - - // make submitRenderViews() actually run - m_renderQueue->setNoRender(); - m_submitRenderViewsSemaphore.release(1); -} - -// Waits to be told to create jobs for the next frame -// Called by QRenderAspect jobsToExecute context of QAspectThread -// Returns all the jobs (and with proper dependency chain) required -// for the rendering of the scene -QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() -{ - QVector<QAspectJobPtr> renderBinJobs; - - // Create the jobs to build the frame - const QVector<QAspectJobPtr> bufferJobs = createRenderBufferJobs(); - - // Remove previous dependencies - m_calculateBoundingVolumeJob->removeDependency(QWeakPointer<QAspectJob>()); - m_cleanupJob->removeDependency(QWeakPointer<QAspectJob>()); - - // Set dependencies - for (const QAspectJobPtr &bufferJob : bufferJobs) - m_calculateBoundingVolumeJob->addDependency(bufferJob); - - m_updateLevelOfDetailJob->setFrameGraphRoot(frameGraphRoot()); - - const BackendNodeDirtySet dirtyBitsForFrame = m_dirtyBits.marked | m_dirtyBits.remaining; - m_dirtyBits.marked = 0; - m_dirtyBits.remaining = 0; - BackendNodeDirtySet notCleared = 0; - - // Add jobs - const bool entitiesEnabledDirty = dirtyBitsForFrame & AbstractRenderer::EntityEnabledDirty; - if (entitiesEnabledDirty) { - renderBinJobs.push_back(m_updateTreeEnabledJob); - // This dependency is added here because we clear all dependencies - // at the start of this function. - m_calculateBoundingVolumeJob->addDependency(m_updateTreeEnabledJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::TransformDirty) { - renderBinJobs.push_back(m_worldTransformJob); - renderBinJobs.push_back(m_updateWorldBoundingVolumeJob); - renderBinJobs.push_back(m_updateShaderDataTransformJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty) { - renderBinJobs.push_back(m_calculateBoundingVolumeJob); - renderBinJobs.push_back(m_updateMeshTriangleListJob); - } - - if (dirtyBitsForFrame & AbstractRenderer::GeometryDirty || - dirtyBitsForFrame & AbstractRenderer::TransformDirty) { - renderBinJobs.push_back(m_expandBoundingVolumeJob); - } - - m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints()); - renderBinJobs.push_back(m_updateSkinningPaletteJob); - renderBinJobs.push_back(m_updateLevelOfDetailJob); - renderBinJobs.push_back(m_cleanupJob); - renderBinJobs.push_back(m_sendRenderCaptureJob); - renderBinJobs.push_back(m_sendBufferCaptureJob); - renderBinJobs.append(bufferJobs); - - // Jobs to prepare GL Resource upload - renderBinJobs.push_back(m_vaoGathererJob); - - if (dirtyBitsForFrame & AbstractRenderer::BuffersDirty) - renderBinJobs.push_back(m_bufferGathererJob); - - if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty) { - renderBinJobs.push_back(m_syncTextureLoadingJob); - renderBinJobs.push_back(m_textureGathererJob); - } - - - // Layer cache is dependent on layers, layer filters and the enabled flag - // on entities - const bool layersDirty = dirtyBitsForFrame & AbstractRenderer::LayersDirty; - const bool layersCacheNeedsToBeRebuilt = layersDirty || entitiesEnabledDirty; - const bool materialDirty = dirtyBitsForFrame & AbstractRenderer::MaterialDirty; - - QMutexLocker lock(m_renderQueue->mutex()); - if (m_renderQueue->wasReset()) { // Have we rendered yet? (Scene3D case) - // Traverse the current framegraph. For each leaf node create a - // RenderView and set its configuration then create a job to - // populate the RenderView with a set of RenderCommands that get - // their details from the RenderNodes that are visible to the - // Camera selected by the framegraph configuration - FrameGraphVisitor visitor(m_nodesManager->frameGraphManager()); - const QVector<FrameGraphNode *> fgLeaves = visitor.traverse(frameGraphRoot()); - - // Remove leaf nodes that no longer exist from cache - const QList<FrameGraphNode *> keys = m_cache.leafNodeCache.keys(); - for (FrameGraphNode *leafNode : keys) { - if (!fgLeaves.contains(leafNode)) - m_cache.leafNodeCache.remove(leafNode); - } - - const int fgBranchCount = fgLeaves.size(); - for (int i = 0; i < fgBranchCount; ++i) { - RenderViewBuilder builder(fgLeaves.at(i), i, this); - builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt); - builder.setMaterialGathererCacheNeedsToBeRebuilt(materialDirty); - builder.prepareJobs(); - renderBinJobs.append(builder.buildJobHierachy()); - } - - // Set target number of RenderViews - m_renderQueue->setTargetRenderViewCount(fgBranchCount); - } else { - // FilterLayerEntityJob is part of the RenderViewBuilder jobs and must be run later - // if none of those jobs are started this frame - notCleared |= AbstractRenderer::EntityEnabledDirty; - notCleared |= AbstractRenderer::LayersDirty; - } - - if (isRunning() && m_submissionContext->isInitialized()) { - if (dirtyBitsForFrame & AbstractRenderer::TechniquesDirty ) - renderBinJobs.push_back(m_filterCompatibleTechniqueJob); - if (dirtyBitsForFrame & AbstractRenderer::ShadersDirty) - renderBinJobs.push_back(m_introspectShaderJob); - } else { - notCleared |= AbstractRenderer::TechniquesDirty; - notCleared |= AbstractRenderer::ShadersDirty; - } - - m_dirtyBits.remaining = dirtyBitsForFrame & notCleared; - - return renderBinJobs; -} - -QAspectJobPtr Renderer::pickBoundingVolumeJob() -{ - // Set values on pickBoundingVolumeJob - RenderSettings *renderSetting = settings(); - if (renderSetting != nullptr) { - m_pickBoundingVolumeJob->setRenderSettings(renderSetting); - m_pickBoundingVolumeJob->setFrameGraphRoot(frameGraphRoot()); - m_pickBoundingVolumeJob->setMouseEvents(pendingPickingEvents()); - m_pickBoundingVolumeJob->setKeyEvents(pendingKeyEvents()); - } - - return m_pickBoundingVolumeJob; -} - -QAspectJobPtr Renderer::rayCastingJob() -{ - // Set values on rayCastingJob - RenderSettings *renderSetting = settings(); - if (renderSetting != nullptr) { - m_rayCastingJob->setRenderSettings(renderSetting); - m_rayCastingJob->setFrameGraphRoot(frameGraphRoot()); - } - - return m_rayCastingJob; -} - -QAspectJobPtr Renderer::syncTextureLoadingJob() -{ - return m_syncTextureLoadingJob; -} - -QAspectJobPtr Renderer::expandBoundingVolumeJob() -{ - return m_expandBoundingVolumeJob; -} - -QAbstractFrameAdvanceService *Renderer::frameAdvanceService() const -{ - return static_cast<Qt3DCore::QAbstractFrameAdvanceService *>(m_vsyncFrameAdvanceService.data()); -} - -// Called by executeCommands -void Renderer::performDraw(RenderCommand *command) -{ - // Indirect Draw Calls - if (command->m_drawIndirect) { - - // Bind the indirect draw buffer - Buffer *indirectDrawBuffer = m_nodesManager->bufferManager()->data(command->m_indirectDrawBuffer); - if (Q_UNLIKELY(indirectDrawBuffer == nullptr)) { - qWarning() << "Invalid Indirect Draw Buffer - failed to retrieve Buffer"; - return; - } - - // Get GLBuffer from Buffer; - GLBuffer *indirectDrawGLBuffer = m_submissionContext->glBufferForRenderBuffer(indirectDrawBuffer, GLBuffer::DrawIndirectBuffer); - if (Q_UNLIKELY(indirectDrawGLBuffer == nullptr)) { - qWarning() << "Invalid Indirect Draw Buffer - failed to retrieve GLBuffer"; - return; - } - - // Bind GLBuffer - const bool successfullyBound = indirectDrawGLBuffer->bind(m_submissionContext.data(), GLBuffer::DrawIndirectBuffer); - - if (Q_LIKELY(successfullyBound)) { - // TO DO: Handle multi draw variants if attribute count > 1 - if (command->m_drawIndexed) { - m_submissionContext->drawElementsIndirect(command->m_primitiveType, - command->m_indexAttributeDataType, - reinterpret_cast<void*>(quintptr(command->m_indirectAttributeByteOffset))); - } else { - m_submissionContext->drawArraysIndirect(command->m_primitiveType, - reinterpret_cast<void*>(quintptr(command->m_indirectAttributeByteOffset))); - } - } else { - qWarning() << "Failed to bind IndirectDrawBuffer"; - } - - } else { // Direct Draw Calls - - // TO DO: Add glMulti Draw variants - if (command->m_primitiveType == QGeometryRenderer::Patches) - m_submissionContext->setVerticesPerPatch(command->m_verticesPerPatch); - - if (command->m_primitiveRestartEnabled) - m_submissionContext->enablePrimitiveRestart(command->m_restartIndexValue); - - // TO DO: Add glMulti Draw variants - if (command->m_drawIndexed) { - Profiling::GLTimeRecorder recorder(Profiling::DrawElement); - m_submissionContext->drawElementsInstancedBaseVertexBaseInstance(command->m_primitiveType, - command->m_primitiveCount, - command->m_indexAttributeDataType, - reinterpret_cast<void*>(quintptr(command->m_indexAttributeByteOffset)), - command->m_instanceCount, - command->m_indexOffset, - command->m_firstVertex); - } else { - Profiling::GLTimeRecorder recorder(Profiling::DrawArray); - m_submissionContext->drawArraysInstancedBaseInstance(command->m_primitiveType, - command->m_firstInstance, - command->m_primitiveCount, - command->m_instanceCount, - command->m_firstVertex); - } - } - -#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG) - int err = m_graphicsContext->openGLContext()->functions()->glGetError(); - if (err) - qCWarning(Rendering) << "GL error after drawing mesh:" << QString::number(err, 16); -#endif - - if (command->m_primitiveRestartEnabled) - m_submissionContext->disablePrimitiveRestart(); -} - -void Renderer::performCompute(const RenderView *, RenderCommand *command) -{ - { - Profiling::GLTimeRecorder recorder(Profiling::ShaderUpdate); - m_submissionContext->activateShader(command->m_shaderDna); - } - { - Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate); - m_submissionContext->setParameters(command->m_parameterPack); - } - { - Profiling::GLTimeRecorder recorder(Profiling::DispatchCompute); - m_submissionContext->dispatchCompute(command->m_workGroups[0], - command->m_workGroups[1], - command->m_workGroups[2]); - } - // HACK: Reset the compute flag to dirty - m_dirtyBits.marked |= AbstractRenderer::ComputeDirty; - -#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG) - int err = m_graphicsContext->openGLContext()->functions()->glGetError(); - if (err) - qCWarning(Rendering) << "GL error after drawing mesh:" << QString::number(err, 16); -#endif -} - -void Renderer::createOrUpdateVAO(RenderCommand *command, - HVao *previousVaoHandle, - OpenGLVertexArrayObject **vao) -{ - const VAOIdentifier vaoKey(command->m_geometry, command->m_shader); - - VAOManager *vaoManager = m_nodesManager->vaoManager(); - command->m_vao = vaoManager->lookupHandle(vaoKey); - - if (command->m_vao.isNull()) { - qCDebug(Rendering) << Q_FUNC_INFO << "Allocating new VAO"; - command->m_vao = vaoManager->getOrAcquireHandle(vaoKey); - vaoManager->data(command->m_vao)->create(m_submissionContext.data(), vaoKey); - } - - if (*previousVaoHandle != command->m_vao) { - *previousVaoHandle = command->m_vao; - *vao = vaoManager->data(command->m_vao); - } - Q_ASSERT(*vao); -} - -// Called by RenderView->submit() in RenderThread context -// Returns true, if all RenderCommands were sent to the GPU -bool Renderer::executeCommandsSubmission(const RenderView *rv) -{ - bool allCommandsIssued = true; - - // Render drawing commands - const QVector<RenderCommand *> commands = rv->commands(); - - // Use the graphicscontext to submit the commands to the underlying - // graphics API (OpenGL) - - // Save the RenderView base stateset - RenderStateSet *globalState = m_submissionContext->currentStateSet(); - OpenGLVertexArrayObject *vao = nullptr; - - for (RenderCommand *command : qAsConst(commands)) { - - if (command->m_type == RenderCommand::Compute) { // Compute Call - performCompute(rv, command); - } else { // Draw Command - // Check if we have a valid command that can be drawn - if (!command->m_isValid) { - allCommandsIssued = false; - continue; - } - - vao = m_nodesManager->vaoManager()->data(command->m_vao); - - // something may have went wrong when initializing the VAO - if (!vao->isSpecified()) { - allCommandsIssued = false; - continue; - } - - { - Profiling::GLTimeRecorder recorder(Profiling::ShaderUpdate); - //// We activate the shader here - if (!m_submissionContext->activateShader(command->m_shaderDna)) { - allCommandsIssued = false; - continue; - } - } - - { - Profiling::GLTimeRecorder recorder(Profiling::VAOUpdate); - // Bind VAO - vao->bind(); - } - - { - Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate); - //// Update program uniforms - if (!m_submissionContext->setParameters(command->m_parameterPack)) { - allCommandsIssued = false; - // If we have failed to set uniform (e.g unable to bind a texture) - // we won't perform the draw call which could show invalid content - continue; - } - } - - //// OpenGL State - // TO DO: Make states not dependendent on their backend node for this step - // Set state - RenderStateSet *localState = command->m_stateSet; - - - { - Profiling::GLTimeRecorder recorder(Profiling::StateUpdate); - // Merge the RenderCommand state with the globalState of the RenderView - // Or restore the globalState if no stateSet for the RenderCommand - if (localState != nullptr) { - command->m_stateSet->merge(globalState); - m_submissionContext->setCurrentStateSet(command->m_stateSet); - } else { - m_submissionContext->setCurrentStateSet(globalState); - } - } - // All Uniforms for a pass are stored in the QUniformPack of the command - // Uniforms for Effect, Material and Technique should already have been correctly resolved - // at that point - - //// Draw Calls - performDraw(command); - } - } // end of RenderCommands loop - - // We cache the VAO and release it only at the end of the exectute frame - // We try to minimize VAO binding between RenderCommands - if (vao) - vao->release(); - - // Reset to the state we were in before executing the render commands - m_submissionContext->setCurrentStateSet(globalState); - - return allCommandsIssued; -} - -bool Renderer::updateVAOWithAttributes(Geometry *geometry, - RenderCommand *command, - Shader *shader, - bool forceUpdate) -{ - m_dirtyAttributes.reserve(m_dirtyAttributes.size() + geometry->attributes().size()); - const auto attributeIds = geometry->attributes(); - - for (QNodeId attributeId : attributeIds) { - // TO DO: Improvement we could store handles and use the non locking policy on the attributeManager - Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); - - if (attribute == nullptr) - return false; - - Buffer *buffer = m_nodesManager->bufferManager()->lookupResource(attribute->bufferId()); - - // Buffer update was already performed at this point - // Just make sure the attribute reference a valid buffer - if (buffer == nullptr) - return false; - - // Index Attribute - bool attributeWasDirty = false; - if (attribute->attributeType() == QAttribute::IndexAttribute) { - if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate) - m_submissionContext->specifyIndices(buffer); - // Vertex Attribute - } else if (command->m_attributes.contains(attribute->nameId())) { - if ((attributeWasDirty = attribute->isDirty()) == true || forceUpdate) { - // Find the location for the attribute - const QVector<ShaderAttribute> shaderAttributes = shader->attributes(); - const ShaderAttribute *attributeDescription = nullptr; - for (const ShaderAttribute &shaderAttribute : shaderAttributes) { - if (shaderAttribute.m_nameId == attribute->nameId()) { - attributeDescription = &shaderAttribute; - break; - } - } - if (!attributeDescription || attributeDescription->m_location < 0) - return false; - m_submissionContext->specifyAttribute(attribute, buffer, attributeDescription); - } - } - - // Append attribute to temporary vector so that its dirtiness - // can be cleared at the end of the frame - if (attributeWasDirty) - m_dirtyAttributes.push_back(attribute); - - // Note: We cannot call unsertDirty on the Attribute at this - // point as we don't know if the attributes are being shared - // with other geometry / geometryRenderer in which case they still - // should remain dirty so that VAO for these commands are properly - // updated - } - - return true; -} - -bool Renderer::requiresVAOAttributeUpdate(Geometry *geometry, - RenderCommand *command) const -{ - const auto attributeIds = geometry->attributes(); - - for (QNodeId attributeId : attributeIds) { - // TO DO: Improvement we could store handles and use the non locking policy on the attributeManager - Attribute *attribute = m_nodesManager->attributeManager()->lookupResource(attributeId); - - if (attribute == nullptr) - continue; - - if ((attribute->attributeType() == QAttribute::IndexAttribute && attribute->isDirty()) || - (command->m_attributes.contains(attribute->nameId()) && attribute->isDirty())) - return true; - } - return false; -} - -// Erase graphics related resources that may become unused after a frame -void Renderer::cleanGraphicsResources() -{ - // Clean buffers - const QVector<Qt3DCore::QNodeId> buffersToRelease = m_nodesManager->bufferManager()->takeBuffersToRelease(); - for (Qt3DCore::QNodeId bufferId : buffersToRelease) - m_submissionContext->releaseBuffer(bufferId); - - // Delete abandoned textures - const QVector<GLTexture*> abandonedTextures = m_nodesManager->glTextureManager()->takeAbandonedTextures(); - for (GLTexture *tex : abandonedTextures) { - tex->destroyGLTexture(); - delete tex; - } - - // Delete abandoned VAOs - m_abandonedVaosMutex.lock(); - const QVector<HVao> abandonedVaos = std::move(m_abandonedVaos); - m_abandonedVaosMutex.unlock(); - for (const HVao &vaoHandle : abandonedVaos) { - // might have already been destroyed last frame, but added by the cleanup job before, so - // check if the VAO is really still existent - OpenGLVertexArrayObject *vao = m_nodesManager->vaoManager()->data(vaoHandle); - if (vao) { - vao->destroy(); - m_nodesManager->vaoManager()->release(vaoHandle); - } - } -} - -QList<QPair<QObject *, QMouseEvent>> Renderer::pendingPickingEvents() const -{ - return m_pickEventFilter->pendingMouseEvents(); -} - -QList<QKeyEvent> Renderer::pendingKeyEvents() const -{ - return m_pickEventFilter->pendingKeyEvents(); -} - -const GraphicsApiFilterData *Renderer::contextInfo() const -{ - return m_submissionContext->contextInfo(); -} - -SubmissionContext *Renderer::submissionContext() const -{ - return m_submissionContext.data(); -} - -void Renderer::addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId) -{ - if (!m_pendingRenderCaptureSendRequests.contains(nodeId)) - m_pendingRenderCaptureSendRequests.push_back(nodeId); -} - -const QVector<Qt3DCore::QNodeId> Renderer::takePendingRenderCaptureSendRequests() -{ - return std::move(m_pendingRenderCaptureSendRequests); -} - -// Returns a vector of jobs to be performed for dirty buffers -// 1 dirty buffer == 1 job, all job can be performed in parallel -QVector<Qt3DCore::QAspectJobPtr> Renderer::createRenderBufferJobs() const -{ - const QVector<QNodeId> dirtyBuffers = m_nodesManager->bufferManager()->takeDirtyBuffers(); - QVector<QAspectJobPtr> dirtyBuffersJobs; - dirtyBuffersJobs.reserve(dirtyBuffers.size()); - - for (const QNodeId bufId : dirtyBuffers) { - Render::HBuffer bufferHandle = m_nodesManager->lookupHandle<Render::Buffer, Render::BufferManager, Render::HBuffer>(bufId); - if (!bufferHandle.isNull()) { - // Create new buffer job - auto job = Render::LoadBufferJobPtr::create(bufferHandle); - job->setNodeManager(m_nodesManager); - dirtyBuffersJobs.push_back(job); - } - } - - return dirtyBuffersJobs; -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h deleted file mode 100644 index b4ad0b0fe..000000000 --- a/src/render/backend/renderer_p.h +++ /dev/null @@ -1,405 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERER_H -#define QT3DRENDER_RENDER_RENDERER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DRender/qrenderaspect.h> -#include <Qt3DRender/qtechnique.h> -#include <Qt3DRender/private/shaderparameterpack_p.h> -#include <Qt3DRender/private/handle_types_p.h> -#include <Qt3DRender/private/abstractrenderer_p.h> -#include <Qt3DCore/qaspectjob.h> -#include <Qt3DRender/private/qt3drender_global_p.h> -#include <Qt3DRender/private/pickboundingvolumejob_p.h> -#include <Qt3DRender/private/raycastingjob_p.h> -#include <Qt3DRender/private/rendersettings_p.h> -#include <Qt3DRender/private/renderviewinitializerjob_p.h> -#include <Qt3DRender/private/expandboundingvolumejob_p.h> -#include <Qt3DRender/private/updateworldtransformjob_p.h> -#include <Qt3DRender/private/calcboundingvolumejob_p.h> -#include <Qt3DRender/private/updateshaderdatatransformjob_p.h> -#include <Qt3DRender/private/framecleanupjob_p.h> -#include <Qt3DRender/private/updateworldboundingvolumejob_p.h> -#include <Qt3DRender/private/updatetreeenabledjob_p.h> -#include <Qt3DRender/private/platformsurfacefilter_p.h> -#include <Qt3DRender/private/sendrendercapturejob_p.h> -#include <Qt3DRender/private/sendbuffercapturejob_p.h> -#include <Qt3DRender/private/genericlambdajob_p.h> -#include <Qt3DRender/private/updatemeshtrianglelistjob_p.h> -#include <Qt3DRender/private/filtercompatibletechniquejob_p.h> -#include <Qt3DRender/private/updateskinningpalettejob_p.h> -#include <Qt3DRender/private/renderercache_p.h> - -#include <QHash> -#include <QMatrix4x4> -#include <QObject> - -#include <QOpenGLShaderProgram> -#include <QOpenGLVertexArrayObject> -#include <QOpenGLBuffer> -#include <QMutex> -#include <QWaitCondition> -#include <QAtomicInt> -#include <QScopedPointer> -#include <QSemaphore> - -#include <functional> - -QT_BEGIN_NAMESPACE - -class QSurface; -class QMouseEvent; - -namespace Qt3DCore { -class QEntity; -class QFrameAllocator; -class QEventFilterService; -} - -namespace Qt3DRender { - -class QCamera; -class QMaterial; -class QShaderProgram; -class QMesh; -class QRenderPass; -class QAbstractShapeMesh; -struct GraphicsApiFilterData; -class QSceneImporter; - -#if QT_CONFIG(qt3d_profile_jobs) -namespace Debug { -class CommandExecuter; -} -#endif - -namespace Render { - -class CameraLens; -class SubmissionContext; -class FrameGraphNode; -class Material; -class Technique; -class Shader; -class Entity; -class RenderCommand; -class RenderQueue; -class RenderView; -class Effect; -class RenderPass; -class RenderThread; -class CommandThread; -class RenderStateSet; -class VSyncFrameAdvanceService; -class PickEventFilter; -class NodeManagers; -class ShaderCache; - -class UpdateLevelOfDetailJob; -typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr; - -using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; -using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>; - -class QT3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer -{ -public: - explicit Renderer(QRenderAspect::RenderType type); - ~Renderer(); - - void dumpInfo() const override; - API api() const override { return AbstractRenderer::OpenGL; } - - qint64 time() const override; - void setTime(qint64 time) override; - - void setNodeManagers(NodeManagers *managers) override; - void setServices(Qt3DCore::QServiceLocator *services) override; - void setSurfaceExposed(bool exposed) override; - - NodeManagers *nodeManagers() const override; - Qt3DCore::QServiceLocator *services() const override { return m_services; } - - void initialize() override; - void shutdown() override; - void releaseGraphicsResources() override; - - void render() override; - void doRender(bool scene3dBlocking = false) override; - void cleanGraphicsResources() override; - - bool isRunning() const override { return m_running.load(); } - - void setSceneRoot(Qt3DCore::QBackendNodeFactory *factory, Entity *sgRoot) override; - Entity *sceneRoot() const override { return m_renderSceneRoot; } - - FrameGraphNode *frameGraphRoot() const override; - - void markDirty(BackendNodeDirtySet changes, BackendNode *node) override; - BackendNodeDirtySet dirtyBits() override; - -#if defined(QT_BUILD_INTERNAL) - void clearDirtyBits(BackendNodeDirtySet changes) override; -#endif - bool shouldRender() override; - void skipNextFrame() override; - - QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override; - Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override; - Qt3DCore::QAspectJobPtr rayCastingJob() override; - Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override; - Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override; - - QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const; - - inline FrameCleanupJobPtr frameCleanupJob() const { return m_cleanupJob; } - inline UpdateShaderDataTransformJobPtr updateShaderDataTransformJob() const { return m_updateShaderDataTransformJob; } - inline CalculateBoundingVolumeJobPtr calculateBoundingVolumeJob() const { return m_calculateBoundingVolumeJob; } - inline UpdateTreeEnabledJobPtr updateTreeEnabledJob() const { return m_updateTreeEnabledJob; } - inline UpdateWorldTransformJobPtr updateWorldTransformJob() const { return m_worldTransformJob; } - inline UpdateWorldBoundingVolumeJobPtr updateWorldBoundingVolumeJob() const { return m_updateWorldBoundingVolumeJob; } - inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; } - inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; } - inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; } - inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; } - inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; } - inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; } - inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; } - inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; } - - Qt3DCore::QAbstractFrameAdvanceService *frameAdvanceService() const override; - - void registerEventFilter(Qt3DCore::QEventFilterService *service) override; - - void setSettings(RenderSettings *settings) override; - RenderSettings *settings() const override; - QOpenGLContext *shareContext() const override; - - - // Executed in secondary GL thread - void loadShader(Shader *shader) const override; - - - void updateGLResources(); - void updateTexture(Texture *texture); - void cleanupTexture(const Texture *texture); - void downloadGLBuffers(); - void blitFramebuffer(Qt3DCore::QNodeId inputRenderTargetId, - Qt3DCore::QNodeId outputRenderTargetId, - QRect inputRect, - QRect outputRect, - GLuint defaultFramebuffer); - - void prepareCommandsSubmission(const QVector<RenderView *> &renderViews); - bool executeCommandsSubmission(const RenderView *rv); - bool updateVAOWithAttributes(Geometry *geometry, - RenderCommand *command, - Shader *shader, - bool forceUpdate); - - bool requiresVAOAttributeUpdate(Geometry *geometry, - RenderCommand *command) const; - - void setOpenGLContext(QOpenGLContext *context); - const GraphicsApiFilterData *contextInfo() const; - SubmissionContext *submissionContext() const; - - inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; } - - QList<QPair<QObject*, QMouseEvent>> pendingPickingEvents() const; - QList<QKeyEvent> pendingKeyEvents() const; - - void addRenderCaptureSendRequest(Qt3DCore::QNodeId nodeId); - const QVector<Qt3DCore::QNodeId> takePendingRenderCaptureSendRequests(); - - void enqueueRenderView(RenderView *renderView, int submitOrder); - bool isReadyToSubmit(); - - QVariant executeCommand(const QStringList &args) override; - void setOffscreenSurfaceHelper(OffscreenSurfaceHelper *helper) override; - QSurfaceFormat format() override; - - struct ViewSubmissionResultData - { - ViewSubmissionResultData() - : lastBoundFBOId(0) - , surface(nullptr) - {} - - uint lastBoundFBOId; - QSurface *surface; - }; - - ViewSubmissionResultData submitRenderViews(const QVector<Render::RenderView *> &renderViews); - - RendererCache *cache() { return &m_cache; } - -#ifdef QT3D_RENDER_UNIT_TESTS -public: -#else - -private: -#endif - bool canRender() const; - - Qt3DCore::QServiceLocator *m_services; - NodeManagers *m_nodesManager; - - // Frame graph root - Qt3DCore::QNodeId m_frameGraphRootUuid; - - Entity *m_renderSceneRoot; - - // Fail safe values that we can use if a RenderCommand - // is missing a shader - RenderStateSet *m_defaultRenderStateSet; - ShaderParameterPack m_defaultUniformPack; - - QScopedPointer<SubmissionContext> m_submissionContext; - QSurfaceFormat m_format; - - RenderQueue *m_renderQueue; - QScopedPointer<RenderThread> m_renderThread; - QScopedPointer<CommandThread> m_commandThread; - QScopedPointer<VSyncFrameAdvanceService> m_vsyncFrameAdvanceService; - - QSemaphore m_submitRenderViewsSemaphore; - QSemaphore m_waitForInitializationToBeCompleted; - - QAtomicInt m_running; - - QScopedPointer<PickEventFilter> m_pickEventFilter; - - QVector<Attribute *> m_dirtyAttributes; - QVector<Geometry *> m_dirtyGeometry; - QAtomicInt m_exposed; - - struct DirtyBits { - BackendNodeDirtySet marked = 0; // marked dirty since last job build - BackendNodeDirtySet remaining = 0; // remaining dirty after jobs have finished - }; - DirtyBits m_dirtyBits; - - QAtomicInt m_lastFrameCorrect; - QOpenGLContext *m_glContext; - QOpenGLContext *m_shareContext; - mutable QMutex m_shareContextMutex; - ShaderCache *m_shaderCache; - PickBoundingVolumeJobPtr m_pickBoundingVolumeJob; - RayCastingJobPtr m_rayCastingJob; - - qint64 m_time; - - RenderSettings *m_settings; - - UpdateShaderDataTransformJobPtr m_updateShaderDataTransformJob; - FrameCleanupJobPtr m_cleanupJob; - UpdateWorldTransformJobPtr m_worldTransformJob; - ExpandBoundingVolumeJobPtr m_expandBoundingVolumeJob; - CalculateBoundingVolumeJobPtr m_calculateBoundingVolumeJob; - UpdateWorldBoundingVolumeJobPtr m_updateWorldBoundingVolumeJob; - UpdateTreeEnabledJobPtr m_updateTreeEnabledJob; - SendRenderCaptureJobPtr m_sendRenderCaptureJob; - SendBufferCaptureJobPtr m_sendBufferCaptureJob; - UpdateSkinningPaletteJobPtr m_updateSkinningPaletteJob; - UpdateLevelOfDetailJobPtr m_updateLevelOfDetailJob; - UpdateMeshTriangleListJobPtr m_updateMeshTriangleListJob; - FilterCompatibleTechniqueJobPtr m_filterCompatibleTechniqueJob; - - QVector<Qt3DCore::QNodeId> m_pendingRenderCaptureSendRequests; - - void performDraw(RenderCommand *command); - void performCompute(const RenderView *rv, RenderCommand *command); - void createOrUpdateVAO(RenderCommand *command, - HVao *previousVAOHandle, - OpenGLVertexArrayObject **vao); - - GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob; - GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob; - IntrospectShadersJobPtr m_introspectShaderJob; - - SynchronizerJobPtr m_syncTextureLoadingJob; - - void lookForAbandonedVaos(); - void lookForDirtyBuffers(); - void lookForDownloadableBuffers(); - void lookForDirtyTextures(); - void reloadDirtyShaders(); - - QMutex m_abandonedVaosMutex; - QVector<HVao> m_abandonedVaos; - - QVector<HBuffer> m_dirtyBuffers; - QVector<HBuffer> m_downloadableBuffers; - QVector<HTexture> m_dirtyTextures; - - bool m_ownedContext; - - OffscreenSurfaceHelper *m_offscreenHelper; - QMutex m_offscreenSurfaceMutex; - -#if QT_CONFIG(qt3d_profile_jobs) - QScopedPointer<Qt3DRender::Debug::CommandExecuter> m_commandExecuter; - friend class Qt3DRender::Debug::CommandExecuter; -#endif - - QMetaObject::Connection m_contextConnection; - RendererCache m_cache; -}; - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERER_H diff --git a/src/render/backend/renderercache_p.h b/src/render/backend/renderercache_p.h deleted file mode 100644 index 2aa50d131..000000000 --- a/src/render/backend/renderercache_p.h +++ /dev/null @@ -1,87 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2017 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERERCACHE_P_H -#define QT3DRENDER_RENDER_RENDERERCACHE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DRender/QFrameGraphNode> - -#include <Qt3DRender/private/entity_p.h> -#include <Qt3DRender/private/renderviewjobutils_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -struct RendererCache -{ - struct LeafNodeData - { - QVector<Entity *> filterEntitiesByLayer; - MaterialParameterGathererData materialParameterGatherer; - }; - - QHash<FrameGraphNode *, LeafNodeData> leafNodeCache; - - QMutex *mutex() { return &m_mutex; } - -private: - QMutex m_mutex; -}; - -} // namespace Render - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERERCACHE_P_H diff --git a/src/render/backend/renderqueue.cpp b/src/render/backend/renderqueue.cpp deleted file mode 100644 index bd9d3ee59..000000000 --- a/src/render/backend/renderqueue.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "renderqueue_p.h" -#include <Qt3DRender/private/renderview_p.h> -#include <QThread> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -RenderQueue::RenderQueue() - : m_noRender(false) - , m_wasReset(true) - , m_targetRenderViewCount(0) - , m_currentRenderViewCount(0) - , m_currentWorkQueue(1) -{ -} - -int RenderQueue::currentRenderViewCount() const -{ - return m_currentRenderViewCount; -} - -/* - * In case the framegraph changed or when the current number of render queue - * needs to be reset. - */ -void RenderQueue::reset() -{ - m_currentRenderViewCount = 0; - m_targetRenderViewCount = 0; - m_currentWorkQueue.clear(); - m_noRender = false; - m_wasReset = true; -} - -void RenderQueue::setNoRender() -{ - Q_ASSERT(m_targetRenderViewCount == 0); - m_noRender = true; -} - -/* - * Queue up a RenderView for the frame being built. - * Thread safe as this is called from the renderer which is locked. - * Returns true if the renderView is complete - */ -bool RenderQueue::queueRenderView(RenderView *renderView, uint submissionOrderIndex) -{ - Q_ASSERT(!m_noRender); - m_currentWorkQueue[submissionOrderIndex] = renderView; - ++m_currentRenderViewCount; - Q_ASSERT(m_currentRenderViewCount <= m_targetRenderViewCount); - return isFrameQueueComplete(); -} - -/* - * Called by the Rendering Thread to retrieve the a frame queue to render. - * A call to reset is required after rendering of the frame. Otherwise under some - * conditions the current but then invalidated frame queue could be reused. - */ -QVector<RenderView *> RenderQueue::nextFrameQueue() -{ - return m_currentWorkQueue; -} - -/* - * Sets the number \a targetRenderViewCount of RenderView objects that make up a frame. - */ -void RenderQueue::setTargetRenderViewCount(int targetRenderViewCount) -{ - Q_ASSERT(!m_noRender); - m_targetRenderViewCount = targetRenderViewCount; - m_currentWorkQueue.resize(targetRenderViewCount); - m_wasReset = false; -} - -/* - * Returns true if all the RenderView objects making up the current frame have been queued. - * Returns false otherwise. - * \note a frameQueue or size 0 is considered incomplete. - */ -bool RenderQueue::isFrameQueueComplete() const -{ - return (m_noRender - || (m_targetRenderViewCount > 0 && m_targetRenderViewCount == m_currentRenderViewCount)); -} - -} // namespace Render - -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/renderqueue_p.h b/src/render/backend/renderqueue_p.h deleted file mode 100644 index e565115f2..000000000 --- a/src/render/backend/renderqueue_p.h +++ /dev/null @@ -1,102 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERQUEUE_H -#define QT3DRENDER_RENDER_RENDERQUEUE_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QVector> -#include <QtGlobal> -#include <QMutex> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -class RenderView; - -class Q_AUTOTEST_EXPORT RenderQueue -{ -public: - RenderQueue(); - - void setTargetRenderViewCount(int targetRenderViewCount); - int targetRenderViewCount() const { return m_targetRenderViewCount; } - int currentRenderViewCount() const; - bool isFrameQueueComplete() const; - - bool queueRenderView(RenderView *renderView, uint submissionOrderIndex); - QVector<RenderView *> nextFrameQueue(); - void reset(); - - void setNoRender(); - inline bool isNoRender() const { return m_noRender; } - - inline bool wasReset() const { return m_wasReset; } - - inline QMutex *mutex() { return &m_mutex; } - -private: - bool m_noRender; - bool m_wasReset; - int m_targetRenderViewCount; - int m_currentRenderViewCount; - QVector<RenderView *> m_currentWorkQueue; - QMutex m_mutex; -}; - -} // namespace Render - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERQUEUE_H diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp deleted file mode 100644 index c29448570..000000000 --- a/src/render/backend/renderview.cpp +++ /dev/null @@ -1,1108 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "renderview_p.h" -#include <Qt3DRender/qmaterial.h> -#include <Qt3DRender/qrenderaspect.h> -#include <Qt3DRender/qrendertarget.h> -#include <Qt3DRender/qabstractlight.h> -#include <Qt3DRender/private/sphere_p.h> - -#include <Qt3DRender/private/cameraselectornode_p.h> -#include <Qt3DRender/private/framegraphnode_p.h> -#include <Qt3DRender/private/layerfilternode_p.h> -#include <Qt3DRender/private/qparameter_p.h> -#include <Qt3DRender/private/cameralens_p.h> -#include <Qt3DRender/private/rendercommand_p.h> -#include <Qt3DRender/private/effect_p.h> -#include <Qt3DRender/private/entity_p.h> -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DRender/private/layer_p.h> -#include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DRender/private/renderpassfilternode_p.h> -#include <Qt3DRender/private/renderpass_p.h> -#include <Qt3DRender/private/geometryrenderer_p.h> -#include <Qt3DRender/private/renderstateset_p.h> -#include <Qt3DRender/private/techniquefilternode_p.h> -#include <Qt3DRender/private/viewportnode_p.h> -#include <Qt3DRender/private/buffermanager_p.h> -#include <Qt3DRender/private/geometryrenderermanager_p.h> -#include <Qt3DRender/private/rendercapture_p.h> -#include <Qt3DRender/private/buffercapture_p.h> -#include <Qt3DRender/private/stringtoint_p.h> -#include <Qt3DCore/qentity.h> -#include <QtGui/qsurface.h> -#include <algorithm> - -#include <QDebug> -#if defined(QT3D_RENDER_VIEW_JOB_TIMINGS) -#include <QElapsedTimer> -#endif - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - - -namespace { - -// register our QNodeId's as a metatype during program loading -const int Q_DECL_UNUSED qNodeIdTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); - -const int MAX_LIGHTS = 8; - -#define LIGHT_POSITION_NAME QLatin1String(".position") -#define LIGHT_TYPE_NAME QLatin1String(".type") -#define LIGHT_COLOR_NAME QLatin1String(".color") -#define LIGHT_INTENSITY_NAME QLatin1String(".intensity") - -int LIGHT_COUNT_NAME_ID = 0; -int LIGHT_POSITION_NAMES[MAX_LIGHTS]; -int LIGHT_TYPE_NAMES[MAX_LIGHTS]; -int LIGHT_COLOR_NAMES[MAX_LIGHTS]; -int LIGHT_INTENSITY_NAMES[MAX_LIGHTS]; -QString LIGHT_STRUCT_NAMES[MAX_LIGHTS]; - -} // anonymous namespace - -bool wasInitialized = false; -RenderView::StandardUniformsNameToTypeHash RenderView::ms_standardUniformSetters; - - -RenderView::StandardUniformsNameToTypeHash RenderView::initializeStandardUniformSetters() -{ - RenderView::StandardUniformsNameToTypeHash setters; - - setters.insert(StringToInt::lookupId(QLatin1String("modelMatrix")), ModelMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("viewMatrix")), ViewMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("projectionMatrix")), ProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("modelView")), ModelViewMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("viewProjectionMatrix")), ViewProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("modelViewProjection")), ModelViewProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("mvp")), ModelViewProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseModelMatrix")), InverseModelMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseViewMatrix")), InverseViewMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseProjectionMatrix")), InverseProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseModelView")), InverseModelViewMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseViewProjectionMatrix")), InverseViewProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseModelViewProjection")), InverseModelViewProjectionMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("modelNormalMatrix")), ModelNormalMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("modelViewNormal")), ModelViewNormalMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("viewportMatrix")), ViewportMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("inverseViewportMatrix")), InverseViewportMatrix); - setters.insert(StringToInt::lookupId(QLatin1String("aspectRatio")), AspectRatio); - setters.insert(StringToInt::lookupId(QLatin1String("exposure")), Exposure); - setters.insert(StringToInt::lookupId(QLatin1String("gamma")), Gamma); - setters.insert(StringToInt::lookupId(QLatin1String("time")), Time); - setters.insert(StringToInt::lookupId(QLatin1String("eyePosition")), EyePosition); - setters.insert(StringToInt::lookupId(QLatin1String("skinningPalette[0]")), SkinningPalette); - - return setters; -} - -// TODO: Move this somewhere global where GraphicsContext::setViewport() can use it too -static QRectF resolveViewport(const QRectF &fractionalViewport, const QSize &surfaceSize) -{ - return QRectF(fractionalViewport.x() * surfaceSize.width(), - (1.0 - fractionalViewport.y() - fractionalViewport.height()) * surfaceSize.height(), - fractionalViewport.width() * surfaceSize.width(), - fractionalViewport.height() * surfaceSize.height()); -} - -static Matrix4x4 getProjectionMatrix(const CameraLens *lens) -{ - if (!lens) - qWarning() << "[Qt3D Renderer] No Camera Lens found. Add a CameraSelector to your Frame Graph or make sure that no entities will be rendered."; - return lens ? lens->projection() : Matrix4x4(); -} - -UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standardUniformType, - Entity *entity, - const Matrix4x4 &model) const -{ - switch (standardUniformType) { - case ModelMatrix: - return UniformValue(model); - case ViewMatrix: - return UniformValue(m_data.m_viewMatrix); - case ProjectionMatrix: - return UniformValue(getProjectionMatrix(m_data.m_renderCameraLens)); - case ModelViewMatrix: - return UniformValue(m_data.m_viewMatrix * model); - case ViewProjectionMatrix: - return UniformValue(getProjectionMatrix(m_data.m_renderCameraLens) * m_data.m_viewMatrix); - case ModelViewProjectionMatrix: - return UniformValue(m_data.m_viewProjectionMatrix * model); - case InverseModelMatrix: - return UniformValue(model.inverted()); - case InverseViewMatrix: - return UniformValue(m_data.m_viewMatrix.inverted()); - case InverseProjectionMatrix: { - return UniformValue(getProjectionMatrix(m_data.m_renderCameraLens).inverted()); - } - case InverseModelViewMatrix: - return UniformValue((m_data.m_viewMatrix * model).inverted()); - case InverseViewProjectionMatrix: { - const Matrix4x4 viewProjectionMatrix = getProjectionMatrix(m_data.m_renderCameraLens) * m_data.m_viewMatrix; - return UniformValue(viewProjectionMatrix.inverted()); - } - case InverseModelViewProjectionMatrix: - return UniformValue((m_data.m_viewProjectionMatrix * model).inverted()); - case ModelNormalMatrix: - return UniformValue(convertToQMatrix4x4(model).normalMatrix()); - case ModelViewNormalMatrix: - return UniformValue(convertToQMatrix4x4(m_data.m_viewMatrix * model).normalMatrix()); - case ViewportMatrix: { - QMatrix4x4 viewportMatrix; - // TO DO: Implement on Matrix4x4 - viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize)); - return UniformValue(Matrix4x4(viewportMatrix)); - } - case InverseViewportMatrix: { - QMatrix4x4 viewportMatrix; - // TO DO: Implement on Matrix4x4 - viewportMatrix.viewport(resolveViewport(m_viewport, m_surfaceSize)); - return UniformValue(Matrix4x4(viewportMatrix.inverted())); - } - case AspectRatio: - return float(m_surfaceSize.width()) / float(m_surfaceSize.height()); - case Exposure: - return UniformValue(m_data.m_renderCameraLens ? m_data.m_renderCameraLens->exposure() : 0.0f); - case Gamma: - return UniformValue(m_gamma); - case Time: - return UniformValue(float(m_renderer->time() / 1000000000.0f)); - case EyePosition: - return UniformValue(m_data.m_eyePos); - case SkinningPalette: { - const Armature *armature = entity->renderComponent<Armature>(); - if (!armature) { - qCWarning(Jobs, "Requesting skinningPalette uniform but no armature set on entity"); - return UniformValue(); - } - return armature->skinningPaletteUniform(); - } - default: - Q_UNREACHABLE(); - return UniformValue(); - } -} - -RenderView::RenderView() - : m_isDownloadBuffersEnable(false) - , m_hasBlitFramebufferInfo(false) - , m_renderer(nullptr) - , m_devicePixelRatio(1.) - , m_viewport(QRectF(0.0f, 0.0f, 1.0f, 1.0f)) - , m_gamma(2.2f) - , m_surface(nullptr) - , m_clearBuffer(QClearBuffers::None) - , m_stateSet(nullptr) - , m_noDraw(false) - , m_compute(false) - , m_frustumCulling(false) - , m_memoryBarrier(QMemoryBarrier::None) - , m_environmentLight(nullptr) -{ - m_workGroups[0] = 1; - m_workGroups[1] = 1; - m_workGroups[2] = 1; - - if (Q_UNLIKELY(!wasInitialized)) { - // Needed as we can control the init order of static/global variables across compile units - // and this hash relies on the static StringToInt class - wasInitialized = true; - RenderView::ms_standardUniformSetters = RenderView::initializeStandardUniformSetters(); - LIGHT_COUNT_NAME_ID = StringToInt::lookupId(QLatin1String("lightCount")); - for (int i = 0; i < MAX_LIGHTS; ++i) { - Q_STATIC_ASSERT_X(MAX_LIGHTS < 10, "can't use the QChar trick anymore"); - LIGHT_STRUCT_NAMES[i] = QLatin1String("lights[") + QLatin1Char(char('0' + i)) + QLatin1Char(']'); - LIGHT_POSITION_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_POSITION_NAME); - LIGHT_TYPE_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_TYPE_NAME); - LIGHT_COLOR_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_COLOR_NAME); - LIGHT_INTENSITY_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_NAMES[i] + LIGHT_INTENSITY_NAME); - } - } -} - -RenderView::~RenderView() -{ - delete m_stateSet; - for (RenderCommand *command : qAsConst(m_commands)) { - delete command->m_stateSet; - delete command; - } -} - -namespace { - -template<int SortType> -struct AdjacentSubRangeFinder -{ - static bool adjacentSubRange(RenderCommand *, RenderCommand *) - { - Q_UNREACHABLE(); - return false; - } -}; - -template<> -struct AdjacentSubRangeFinder<QSortPolicy::StateChangeCost> -{ - static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) - { - return a->m_changeCost == b->m_changeCost; - } -}; - -template<> -struct AdjacentSubRangeFinder<QSortPolicy::BackToFront> -{ - static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) - { - return a->m_depth == b->m_depth; - } -}; - -template<> -struct AdjacentSubRangeFinder<QSortPolicy::Material> -{ - static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) - { - return a->m_shaderDna == b->m_shaderDna; - } -}; - -template<> -struct AdjacentSubRangeFinder<QSortPolicy::FrontToBack> -{ - static bool adjacentSubRange(RenderCommand *a, RenderCommand *b) - { - return a->m_depth == b->m_depth; - } -}; - -template<typename Predicate> -int advanceUntilNonAdjacent(const QVector<RenderCommand *> &commands, - const int beg, const int end, Predicate pred) -{ - int i = beg + 1; - while (i < end) { - if (!pred(*(commands.begin() + beg), *(commands.begin() + i))) - break; - ++i; - } - return i; -} - - -using CommandIt = QVector<RenderCommand *>::iterator; - -template<int SortType> -struct SubRangeSorter -{ - static void sortSubRange(CommandIt begin, const CommandIt end) - { - Q_UNUSED(begin); - Q_UNUSED(end); - Q_UNREACHABLE(); - } -}; - -template<> -struct SubRangeSorter<QSortPolicy::StateChangeCost> -{ - static void sortSubRange(CommandIt begin, const CommandIt end) - { - std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { - return a->m_changeCost > b->m_changeCost; - }); - } -}; - -template<> -struct SubRangeSorter<QSortPolicy::BackToFront> -{ - static void sortSubRange(CommandIt begin, const CommandIt end) - { - std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { - return a->m_depth > b->m_depth; - }); - } -}; - -template<> -struct SubRangeSorter<QSortPolicy::Material> -{ - static void sortSubRange(CommandIt begin, const CommandIt end) - { - // First we sort by shaderDNA - std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { - return a->m_shaderDna > b->m_shaderDna; - }); - } -}; - -template<> -struct SubRangeSorter<QSortPolicy::FrontToBack> -{ - static void sortSubRange(CommandIt begin, const CommandIt end) - { - std::stable_sort(begin, end, [] (RenderCommand *a, RenderCommand *b) { - return a->m_depth < b->m_depth; - }); - } -}; - -int findSubRange(const QVector<RenderCommand *> &commands, - const int begin, const int end, - const QSortPolicy::SortType sortType) -{ - switch (sortType) { - case QSortPolicy::StateChangeCost: - return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::StateChangeCost>::adjacentSubRange); - case QSortPolicy::BackToFront: - return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::BackToFront>::adjacentSubRange); - case QSortPolicy::Material: - return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); - case QSortPolicy::FrontToBack: - return advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::FrontToBack>::adjacentSubRange); - default: - Q_UNREACHABLE(); - return end; - } -} - -void sortByMaterial(QVector<RenderCommand *> &commands, int begin, const int end) -{ - // We try to arrange elements so that their rendering cost is minimized for a given shader - int rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); - while (begin != end) { - if (begin + 1 < rangeEnd) { - std::stable_sort(commands.begin() + begin + 1, commands.begin() + rangeEnd, [] (RenderCommand *a, RenderCommand *b){ - return a->m_material.handle() < b->m_material.handle(); - }); - } - begin = rangeEnd; - rangeEnd = advanceUntilNonAdjacent(commands, begin, end, AdjacentSubRangeFinder<QSortPolicy::Material>::adjacentSubRange); - } -} - -void sortCommandRange(QVector<RenderCommand *> &commands, int begin, const int end, const int level, - const QVector<Qt3DRender::QSortPolicy::SortType> &sortingTypes) -{ - if (level >= sortingTypes.size()) - return; - - switch (sortingTypes.at(level)) { - case QSortPolicy::StateChangeCost: - SubRangeSorter<QSortPolicy::StateChangeCost>::sortSubRange(commands.begin() + begin, commands.begin() + end); - break; - case QSortPolicy::BackToFront: - SubRangeSorter<QSortPolicy::BackToFront>::sortSubRange(commands.begin() + begin, commands.begin() + end); - break; - case QSortPolicy::Material: - // Groups all same shader DNA together - SubRangeSorter<QSortPolicy::Material>::sortSubRange(commands.begin() + begin, commands.begin() + end); - // Group all same material together (same parameters most likely) - sortByMaterial(commands, begin, end); - break; - case QSortPolicy::FrontToBack: - SubRangeSorter<QSortPolicy::FrontToBack>::sortSubRange(commands.begin() + begin, commands.begin() + end); - break; - default: - Q_UNREACHABLE(); - } - - // For all sub ranges of adjacent item for sortType[i] - // Perform filtering with sortType[i + 1] - int rangeEnd = findSubRange(commands, begin, end, sortingTypes.at(level)); - while (begin != end) { - sortCommandRange(commands, begin, rangeEnd, level + 1, sortingTypes); - begin = rangeEnd; - rangeEnd = findSubRange(commands, begin, end, sortingTypes.at(level)); - } -} - -} // anonymous - -void RenderView::sort() -{ - sortCommandRange(m_commands, 0, m_commands.size(), 0, m_data.m_sortingTypes); - - // For RenderCommand with the same shader - // We compute the adjacent change cost - - // Minimize uniform changes - int i = 0; - while (i < m_commands.size()) { - int j = i; - - // Advance while commands share the same shader - while (i < m_commands.size() && m_commands[j]->m_shaderDna == m_commands[i]->m_shaderDna) - ++i; - - if (i - j > 0) { // Several commands have the same shader, so we minimize uniform changes - PackUniformHash cachedUniforms = m_commands[j++]->m_parameterPack.uniforms(); - - while (j < i) { - // We need the reference here as we are modifying the original container - // not the copy - PackUniformHash &uniforms = m_commands.at(j)->m_parameterPack.m_uniforms; - PackUniformHash::iterator it = uniforms.begin(); - const PackUniformHash::iterator end = uniforms.end(); - - while (it != end) { - // We are comparing the values: - // - raw uniform values - // - the texture Node id if the uniform represents a texture - // since all textures are assigned texture units before the RenderCommands - // sharing the same material (shader) are rendered, we can't have the case - // where two uniforms, referencing the same texture eventually have 2 different - // texture unit values - const UniformValue refValue = cachedUniforms.value(it.key()); - if (it.value() == refValue) { - it = uniforms.erase(it); - } else { - cachedUniforms.insert(it.key(), it.value()); - ++it; - } - } - ++j; - } - } - } -} - -void RenderView::setRenderer(Renderer *renderer) -{ - m_renderer = renderer; - m_manager = renderer->nodeManagers(); -} - -void RenderView::addClearBuffers(const ClearBuffers *cb) { - QClearBuffers::BufferTypeFlags type = cb->type(); - - if (type & QClearBuffers::StencilBuffer) { - m_clearStencilValue = cb->clearStencilValue(); - m_clearBuffer |= QClearBuffers::StencilBuffer; - } - if (type & QClearBuffers::DepthBuffer) { - m_clearDepthValue = cb->clearDepthValue(); - m_clearBuffer |= QClearBuffers::DepthBuffer; - } - // keep track of global ClearColor (if set) and collect all DrawBuffer-specific - // ClearColors - if (type & QClearBuffers::ColorBuffer) { - ClearBufferInfo clearBufferInfo; - clearBufferInfo.clearColor = cb->clearColor(); - - if (cb->clearsAllColorBuffers()) { - m_globalClearColorBuffer = clearBufferInfo; - m_clearBuffer |= QClearBuffers::ColorBuffer; - } else { - if (cb->bufferId()) { - const RenderTargetOutput *targetOutput = m_manager->attachmentManager()->lookupResource(cb->bufferId()); - if (targetOutput) { - clearBufferInfo.attchmentPoint = targetOutput->point(); - // Note: a job is later performed to find the drawIndex from the buffer attachment point - // using the AttachmentPack - m_specificClearColorBuffers.push_back(clearBufferInfo); - } - } - } - } -} - -// If we are there, we know that entity had a GeometryRenderer + Material -QVector<RenderCommand *> RenderView::buildDrawRenderCommands(const QVector<Entity *> &entities) const -{ - // Note: since many threads can be building render commands - // we need to ensure that the UniformBlockValueBuilder they are using - // is only accessed from the same thread - UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); - builder->shaderDataManager = m_manager->shaderDataManager(); - builder->textureManager = m_manager->textureManager(); - m_localData.setLocalData(builder); - - QVector<RenderCommand *> commands; - commands.reserve(entities.size()); - - for (Entity *entity : entities) { - GeometryRenderer *geometryRenderer = nullptr; - HGeometryRenderer geometryRendererHandle = entity->componentHandle<GeometryRenderer>(); - - // There is a geometry renderer with geometry - if ((geometryRenderer = m_manager->geometryRendererManager()->data(geometryRendererHandle)) != nullptr - && geometryRenderer->isEnabled() - && !geometryRenderer->geometryId().isNull()) { - - const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>(); - const HMaterial materialHandle = entity->componentHandle<Material>(); - const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId); - HGeometry geometryHandle = m_manager->lookupHandle<Geometry, GeometryManager, HGeometry>(geometryRenderer->geometryId()); - Geometry *geometry = m_manager->data<Geometry, GeometryManager>(geometryHandle); - - // 1 RenderCommand per RenderPass pass on an Entity with a Mesh - for (const RenderPassParameterData &passData : renderPassData) { - // Add the RenderPass Parameters - RenderCommand *command = new RenderCommand(); - - // Project the camera-to-object-center vector onto the camera - // view vector. This gives a depth value suitable as the key - // for BackToFront sorting. - command->m_depth = Vector3D::dotProduct(entity->worldBoundingVolume()->center() - m_data.m_eyePos, m_data.m_eyeViewDir); - - command->m_geometry = geometryHandle; - command->m_geometryRenderer = geometryRendererHandle; - command->m_material = materialHandle; - // For RenderPass based states we use the globally set RenderState - // if no renderstates are defined as part of the pass. That means: - // RenderPass { renderStates: [] } will use the states defined by - // StateSet in the FrameGraph - RenderPass *pass = passData.pass; - if (pass->hasRenderStates()) { - command->m_stateSet = new RenderStateSet(); - addToRenderStateSet(command->m_stateSet, pass->renderStates(), m_manager->renderStateManager()); - - // Merge per pass stateset with global stateset - // so that the local stateset only overrides - if (m_stateSet != nullptr) - command->m_stateSet->merge(m_stateSet); - command->m_changeCost = m_renderer->defaultRenderState()->changeCost(command->m_stateSet); - } - - // Pick which lights to take in to account. - // For now decide based on the distance by taking the MAX_LIGHTS closest lights. - // Replace with more sophisticated mechanisms later. - // Copy vector so that we can sort it concurrently and we only want to sort the one for the current command - QVector<LightSource> lightSources = m_lightSources; - if (lightSources.size() > 1) { - const Vector3D entityCenter = entity->worldBoundingVolume()->center(); - std::sort(lightSources.begin(), lightSources.end(), - [&] (const LightSource &a, const LightSource &b) { - const float distA = entityCenter.distanceToPoint(a.entity->worldBoundingVolume()->center()); - const float distB = entityCenter.distanceToPoint(b.entity->worldBoundingVolume()->center()); - return distA < distB; - }); - } - - ParameterInfoList globalParameters = passData.parameterInfo; - // setShaderAndUniforms can initialize a localData - // make sure this is cleared before we leave this function - setShaderAndUniforms(command, - pass, - globalParameters, - entity, - lightSources.mid(0, std::max(lightSources.size(), MAX_LIGHTS)), - m_environmentLight); - - // Store all necessary information for actual drawing if command is valid - command->m_isValid = !command->m_attributes.empty(); - if (command->m_isValid) { - // Update the draw command with what's going to be needed for the drawing - uint primitiveCount = geometryRenderer->vertexCount(); - uint estimatedCount = 0; - Attribute *indexAttribute = nullptr; - - const QVector<Qt3DCore::QNodeId> attributeIds = geometry->attributes(); - for (Qt3DCore::QNodeId attributeId : attributeIds) { - Attribute *attribute = m_manager->attributeManager()->lookupResource(attributeId); - if (attribute->attributeType() == QAttribute::IndexAttribute) - indexAttribute = attribute; - else if (command->m_attributes.contains(attribute->nameId())) - estimatedCount = qMax(attribute->count(), estimatedCount); - } - - // Update the draw command with all the information required for the drawing - command->m_drawIndexed = (indexAttribute != nullptr); - if (command->m_drawIndexed) { - command->m_indexAttributeDataType = GraphicsContext::glDataTypeFromAttributeDataType(indexAttribute->vertexBaseType()); - command->m_indexAttributeByteOffset = indexAttribute->byteOffset(); - } - - // Use the count specified by the GeometryRender - // If not specified use the indexAttribute count if present - // Otherwise tries to use the count from the attribute with the highest count - if (primitiveCount == 0) { - if (indexAttribute) - primitiveCount = indexAttribute->count(); - else - primitiveCount = estimatedCount; - } - - command->m_primitiveCount = primitiveCount; - command->m_primitiveType = geometryRenderer->primitiveType(); - command->m_primitiveRestartEnabled = geometryRenderer->primitiveRestartEnabled(); - command->m_restartIndexValue = geometryRenderer->restartIndexValue(); - command->m_firstInstance = geometryRenderer->firstInstance(); - command->m_instanceCount = geometryRenderer->instanceCount(); - command->m_firstVertex = geometryRenderer->firstVertex(); - command->m_indexOffset = geometryRenderer->indexOffset(); - command->m_verticesPerPatch = geometryRenderer->verticesPerPatch(); - } - - commands.append(command); - } - } - } - - // We reset the local data once we are done with it - m_localData.setLocalData(nullptr); - - return commands; -} - -QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<Entity *> &entities) const -{ - // Note: since many threads can be building render commands - // we need to ensure that the UniformBlockValueBuilder they are using - // is only accessed from the same thread - UniformBlockValueBuilder *builder = new UniformBlockValueBuilder(); - builder->shaderDataManager = m_manager->shaderDataManager(); - builder->textureManager = m_manager->textureManager(); - m_localData.setLocalData(builder); - - // If the RenderView contains only a ComputeDispatch then it cares about - // A ComputeDispatch is also implicitely a NoDraw operation - // enabled flag - // layer component - // material/effect/technique/parameters/filters/ - QVector<RenderCommand *> commands; - commands.reserve(entities.size()); - for (Entity *entity : entities) { - ComputeCommand *computeJob = nullptr; - if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr - && computeJob->isEnabled()) { - - const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>(); - const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId); - - // 1 RenderCommand per RenderPass pass on an Entity with a Mesh - for (const RenderPassParameterData &passData : renderPassData) { - // Add the RenderPass Parameters - ParameterInfoList globalParameters = passData.parameterInfo; - RenderPass *pass = passData.pass; - parametersFromParametersProvider(&globalParameters, m_manager->parameterManager(), pass); - - RenderCommand *command = new RenderCommand(); - command->m_type = RenderCommand::Compute; - command->m_workGroups[0] = std::max(m_workGroups[0], computeJob->x()); - command->m_workGroups[1] = std::max(m_workGroups[1], computeJob->y()); - command->m_workGroups[2] = std::max(m_workGroups[2], computeJob->z()); - setShaderAndUniforms(command, - pass, - globalParameters, - entity, - QVector<LightSource>(), - nullptr); - commands.append(command); - } - } - } - - // We reset the local data once we are done with it - m_localData.setLocalData(nullptr); - - return commands; -} - -void RenderView::updateMatrices() -{ - if (m_data.m_renderCameraNode && m_data.m_renderCameraLens && m_data.m_renderCameraLens->isEnabled()) { - const Matrix4x4 cameraWorld = *(m_data.m_renderCameraNode->worldTransform()); - setViewMatrix(m_data.m_renderCameraLens->viewMatrix(cameraWorld)); - - setViewProjectionMatrix(m_data.m_renderCameraLens->projection() * viewMatrix()); - //To get the eyePosition of the camera, we need to use the inverse of the - //camera's worldTransform matrix. - const Matrix4x4 inverseWorldTransform = viewMatrix().inverted(); - const Vector3D eyePosition(inverseWorldTransform.column(3)); - setEyePosition(eyePosition); - - // Get the viewing direction of the camera. Use the normal matrix to - // ensure non-uniform scale works too. - const QMatrix3x3 normalMat = convertToQMatrix4x4(m_data.m_viewMatrix).normalMatrix(); - // dir = normalize(QVector3D(0, 0, -1) * normalMat) - setEyeViewDirection(Vector3D(-normalMat(2, 0), -normalMat(2, 1), -normalMat(2, 2)).normalized()); - } -} - -void RenderView::setUniformValue(ShaderParameterPack &uniformPack, int nameId, const UniformValue &value) const -{ - // At this point a uniform value can only be a scalar type - // or a Qt3DCore::QNodeId corresponding to a Texture - // ShaderData/Buffers would be handled as UBO/SSBO and would therefore - // not be in the default uniform block - if (value.valueType() == UniformValue::NodeId) { - const Qt3DCore::QNodeId *nodeIds = value.constData<Qt3DCore::QNodeId>(); - - const int uniformArraySize = value.byteSize() / sizeof(Qt3DCore::QNodeId); - for (int i = 0; i < uniformArraySize; ++i) { - const Qt3DCore::QNodeId texId = nodeIds[i]; - const Texture *tex = m_manager->textureManager()->lookupResource(texId); - if (tex != nullptr) - uniformPack.setTexture(nameId, i, texId); - } - - UniformValue textureValue(uniformArraySize * sizeof(int), UniformValue::TextureValue); - std::fill(textureValue.data<int>(), textureValue.data<int>() + uniformArraySize, -1); - uniformPack.setUniform(nameId, textureValue); - } else { - uniformPack.setUniform(nameId, value); - } -} - -void RenderView::setStandardUniformValue(ShaderParameterPack &uniformPack, - int glslNameId, - int nameId, - Entity *entity, - const Matrix4x4 &worldTransform) const -{ - uniformPack.setUniform(glslNameId, standardUniformValue(ms_standardUniformSetters[nameId], entity, worldTransform)); -} - -void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, - Shader *shader, - const ShaderUniformBlock &block, - const UniformValue &value) const -{ - Q_UNUSED(shader) - - if (value.valueType() == UniformValue::NodeId) { - - Buffer *buffer = nullptr; - if ((buffer = m_manager->bufferManager()->lookupResource(*value.constData<Qt3DCore::QNodeId>())) != nullptr) { - BlockToUBO uniformBlockUBO; - uniformBlockUBO.m_blockIndex = block.m_index; - uniformBlockUBO.m_bufferID = buffer->peerId(); - uniformBlockUBO.m_needsUpdate = false; - uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); - // Buffer update to GL buffer will be done at render time - } - - - //ShaderData *shaderData = nullptr; - // if ((shaderData = m_manager->shaderDataManager()->lookupResource(value.value<Qt3DCore::QNodeId>())) != nullptr) { - // UBO are indexed by <ShaderId, ShaderDataId> so that a same QShaderData can be used among different shaders - // while still making sure that if they have a different layout everything will still work - // If two shaders define the same block with the exact same layout, in that case the UBO could be shared - // but how do we know that ? We'll need to compare ShaderUniformBlocks - - // Note: we assume that if a buffer is shared across multiple shaders - // then it implies that they share the same layout - - // Temporarly disabled - - // BufferShaderKey uboKey(shaderData->peerId(), - // shader->peerId()); - - // BlockToUBO uniformBlockUBO; - // uniformBlockUBO.m_blockIndex = block.m_index; - // uniformBlockUBO.m_shaderDataID = shaderData->peerId(); - // bool uboNeedsUpdate = false; - - // // build UBO at uboId if not created before - // if (!m_manager->glBufferManager()->contains(uboKey)) { - // m_manager->glBufferManager()->getOrCreateResource(uboKey); - // uboNeedsUpdate = true; - // } - - // // If shaderData has been updated (property has changed or one of the nested properties has changed) - // // foreach property defined in the QShaderData, we try to fill the value of the corresponding active uniform(s) - // // for all the updated properties (all the properties if the UBO was just created) - // if (shaderData->updateViewTransform(*m_data->m_viewMatrix) || uboNeedsUpdate) { - // // Clear previous values remaining in the hash - // m_data->m_uniformBlockBuilder.activeUniformNamesToValue.clear(); - // // Update only update properties if uboNeedsUpdate is true, otherwise update the whole block - // m_data->m_uniformBlockBuilder.updatedPropertiesOnly = uboNeedsUpdate; - // // Retrieve names and description of each active uniforms in the uniform block - // m_data->m_uniformBlockBuilder.uniforms = shader->activeUniformsForUniformBlock(block.m_index); - // // Builds the name-value map for the block - // m_data->m_uniformBlockBuilder.buildActiveUniformNameValueMapStructHelper(shaderData, block.m_name); - // if (!uboNeedsUpdate) - // shaderData->markDirty(); - // // copy the name-value map into the BlockToUBO - // uniformBlockUBO.m_updatedProperties = m_data->m_uniformBlockBuilder.activeUniformNamesToValue; - // uboNeedsUpdate = true; - // } - - // uniformBlockUBO.m_needsUpdate = uboNeedsUpdate; - // uniformPack.setUniformBuffer(std::move(uniformBlockUBO)); - // } - } -} - -void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, - Shader *shader, - const ShaderStorageBlock &block, - const UniformValue &value) const -{ - Q_UNUSED(shader) - if (value.valueType() == UniformValue::NodeId) { - Buffer *buffer = nullptr; - if ((buffer = m_manager->bufferManager()->lookupResource(*value.constData<Qt3DCore::QNodeId>())) != nullptr) { - BlockToSSBO shaderStorageBlock; - shaderStorageBlock.m_blockIndex = block.m_index; - shaderStorageBlock.m_bufferID = buffer->peerId(); - uniformPack.setShaderStorageBuffer(shaderStorageBlock); - // Buffer update to GL buffer will be done at render time - } - } -} - -void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, Shader *shader, ShaderData *shaderData, const QString &structName) const -{ - UniformBlockValueBuilder *builder = m_localData.localData(); - builder->activeUniformNamesToValue.clear(); - - // Set the view matrix to be used to transform "Transformed" properties in the ShaderData - builder->viewMatrix = m_data.m_viewMatrix; - // Force to update the whole block - builder->updatedPropertiesOnly = false; - // Retrieve names and description of each active uniforms in the uniform block - builder->uniforms = shader->activeUniformsForUniformBlock(-1); - // Build name-value map for the block - builder->buildActiveUniformNameValueMapStructHelper(shaderData, structName); - // Set uniform values for each entrie of the block name-value map - QHash<int, QVariant>::const_iterator activeValuesIt = builder->activeUniformNamesToValue.constBegin(); - const QHash<int, QVariant>::const_iterator activeValuesEnd = builder->activeUniformNamesToValue.constEnd(); - - // TO DO: Make the ShaderData store UniformValue - while (activeValuesIt != activeValuesEnd) { - setUniformValue(uniformPack, activeValuesIt.key(), UniformValue::fromVariant(activeValuesIt.value())); - ++activeValuesIt; - } -} - -void RenderView::setShaderAndUniforms(RenderCommand *command, - RenderPass *rPass, - ParameterInfoList ¶meters, - Entity *entity, - const QVector<LightSource> &activeLightSources, - EnvironmentLight *environmentLight) const -{ - // The VAO Handle is set directly in the renderer thread so as to avoid having to use a mutex here - // Set shader, technique, and effect by basically doing : - // ShaderProgramManager[MaterialManager[frontentEntity->id()]->Effect->Techniques[TechniqueFilter->name]->RenderPasses[RenderPassFilter->name]]; - // The Renderer knows that if one of those is null, a default material / technique / effect as to be used - - // Find all RenderPasses (in order) matching values set in the RenderPassFilter - // Get list of parameters for the Material, Effect, and Technique - // For each ParameterBinder in the RenderPass -> create a QUniformPack - // Once that works, improve that to try and minimize QUniformPack updates - - if (rPass != nullptr) { - // Index Shader by Shader UUID - command->m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(rPass->shaderProgram()); - Shader *shader = m_manager->data<Shader, ShaderManager>(command->m_shader); - if (shader != nullptr && shader->isLoaded()) { - command->m_shaderDna = shader->dna(); - - // Builds the QUniformPack, sets shader standard uniforms and store attributes name / glname bindings - // If a parameter is defined and not found in the bindings it is assumed to be a binding of Uniform type with the glsl name - // equals to the parameter name - const QVector<int> uniformNamesIds = shader->uniformsNamesIds(); - const QVector<int> uniformBlockNamesIds = shader->uniformBlockNamesIds(); - const QVector<int> shaderStorageBlockNamesIds = shader->storageBlockNamesIds(); - const QVector<int> attributeNamesIds = shader->attributeNamesIds(); - - // Set fragData Name and index - // Later on we might want to relink the shader if attachments have changed - // But for now we set them once and for all - QHash<QString, int> fragOutputs; - if (!m_renderTarget.isNull() && !shader->isLoaded()) { - const auto atts = m_attachmentPack.attachments(); - for (const Attachment &att : atts) { - if (att.m_point <= QRenderTargetOutput::Color15) - fragOutputs.insert(att.m_name, att.m_point); - } - } - - if (!uniformNamesIds.isEmpty() || !attributeNamesIds.isEmpty() || - !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) { - - // Set default standard uniforms without bindings - const Matrix4x4 worldTransform = *(entity->worldTransform()); - for (const int uniformNameId : uniformNamesIds) { - if (ms_standardUniformSetters.contains(uniformNameId)) - setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform); - } - - // Set default attributes - for (const int attributeNameId : attributeNamesIds) - command->m_attributes.push_back(attributeNameId); - - // Parameters remaining could be - // -> uniform scalar / vector - // -> uniform struct / arrays - // -> uniform block / array (4.3) - // -> ssbo block / array (4.3) - - ParameterInfoList::const_iterator it = parameters.cbegin(); - const ParameterInfoList::const_iterator parametersEnd = parameters.cend(); - - while (it != parametersEnd) { - Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle); - const UniformValue &uniformValue = param->uniformValue(); - if (uniformNamesIds.contains(it->nameId)) { // Parameter is a regular uniform - setUniformValue(command->m_parameterPack, it->nameId, uniformValue); - } else if (uniformBlockNamesIds.indexOf(it->nameId) != -1) { // Parameter is a uniform block - setUniformBlockValue(command->m_parameterPack, shader, shader->uniformBlockForBlockNameId(it->nameId), uniformValue); - } else if (shaderStorageBlockNamesIds.indexOf(it->nameId) != -1) { // Parameters is a SSBO - setShaderStorageValue(command->m_parameterPack, shader, shader->storageBlockForBlockNameId(it->nameId), uniformValue); - } else { // Parameter is a struct - ShaderData *shaderData = nullptr; - if (uniformValue.valueType() == UniformValue::NodeId && - (shaderData = m_manager->shaderDataManager()->lookupResource(*uniformValue.constData<Qt3DCore::QNodeId>())) != nullptr) { - // Try to check if we have a struct or array matching a QShaderData parameter - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, StringToInt::lookupString(it->nameId)); - } - // Otherwise: param unused by current shader - } - ++it; - } - - // Lights - - int lightIdx = 0; - for (const LightSource &lightSource : activeLightSources) { - if (lightIdx == MAX_LIGHTS) - break; - Entity *lightEntity = lightSource.entity; - const Vector3D worldPos = lightEntity->worldBoundingVolume()->center(); - for (Light *light : lightSource.lights) { - if (!light->isEnabled()) - continue; - - ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData()); - if (!shaderData) - continue; - - if (lightIdx == MAX_LIGHTS) - break; - - // Note: implicit conversion of values to UniformValue - setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[lightIdx], worldPos); - setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f)); - setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[lightIdx], 0.5f); - - // There is no risk in doing that even if multithreaded - // since we are sure that a shaderData is unique for a given light - // and won't ever be referenced as a Component either - Matrix4x4 *worldTransform = lightEntity->worldTransform(); - if (worldTransform) - shaderData->updateWorldTransform(*worldTransform); - - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_NAMES[lightIdx]); - ++lightIdx; - } - } - - if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID)) - setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax(1, lightIdx))); - - // If no active light sources and no environment light, add a default light - if (activeLightSources.isEmpty() && !environmentLight) { - // Note: implicit conversion of values to UniformValue - setUniformValue(command->m_parameterPack, LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f)); - setUniformValue(command->m_parameterPack, LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f)); - setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_NAMES[0], 0.5f); - } - - // Environment Light - int envLightCount = 0; - if (environmentLight && environmentLight->isEnabled()) { - ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(environmentLight->shaderData()); - if (shaderData) { - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, QStringLiteral("envLight")); - envLightCount = 1; - } - } - setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount); - } - // Set frag outputs in the shaders if hash not empty - if (!fragOutputs.isEmpty()) - shader->setFragOutputs(fragOutputs); - } - } - else { - qCWarning(Render::Backend) << Q_FUNC_INFO << "Using default effect as none was provided"; - } -} - -bool RenderView::hasBlitFramebufferInfo() const -{ - return m_hasBlitFramebufferInfo; -} - -void RenderView::setHasBlitFramebufferInfo(bool hasBlitFramebufferInfo) -{ - m_hasBlitFramebufferInfo = hasBlitFramebufferInfo; -} - -BlitFramebufferInfo RenderView::blitFrameBufferInfo() const -{ - return m_blitFrameBufferInfo; -} - -void RenderView::setBlitFrameBufferInfo(const BlitFramebufferInfo &blitFrameBufferInfo) -{ - m_blitFrameBufferInfo = blitFrameBufferInfo; -} - -bool RenderView::isDownloadBuffersEnable() const -{ - return m_isDownloadBuffersEnable; -} - -void RenderView::setIsDownloadBuffersEnable(bool isDownloadBuffersEnable) -{ - m_isDownloadBuffersEnable = isDownloadBuffersEnable; -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/renderview_p.h b/src/render/backend/renderview_p.h deleted file mode 100644 index cb3c74917..000000000 --- a/src/render/backend/renderview_p.h +++ /dev/null @@ -1,392 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Copyright (C) 2016 The Qt Company Ltd and/or its subsidiary(-ies). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERVIEW_H -#define QT3DRENDER_RENDER_RENDERVIEW_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DRender/qparameter.h> -#include <Qt3DRender/qclearbuffers.h> -#include <Qt3DRender/qlayerfilter.h> -#include <Qt3DRender/private/renderer_p.h> -#include <Qt3DRender/private/clearbuffers_p.h> -#include <Qt3DRender/private/cameralens_p.h> -#include <Qt3DRender/private/attachmentpack_p.h> -#include <Qt3DRender/private/handle_types_p.h> -#include <Qt3DRender/private/qsortpolicy_p.h> -#include <Qt3DRender/private/lightsource_p.h> -#include <Qt3DRender/private/qmemorybarrier_p.h> -#include <Qt3DRender/private/qrendercapture_p.h> -#include <Qt3DRender/private/qblitframebuffer_p.h> - -#include <Qt3DCore/private/qframeallocator_p.h> -#include <Qt3DRender/private/aligned_malloc_p.h> - -// TODO: Move out once this is all refactored -#include <Qt3DRender/private/renderviewjobutils_p.h> - -#include <QVector> -#include <QSurface> -#include <QMutex> -#include <QColor> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -class QRenderPass; - -namespace Render { - -class Renderer; -class NodeManagers; -class RenderCommand; -class RenderPassFilter; -class TechniqueFilter; -class ViewportNode; -class Effect; -class RenderPass; - -typedef QPair<ShaderUniform, QVariant> ActivePropertyContent; -typedef QPair<QString, ActivePropertyContent > ActiveProperty; - -struct Q_AUTOTEST_EXPORT Plane -{ - explicit Plane(const Vector4D &planeEquation) - : planeEquation(planeEquation) - , normal(Vector3D(planeEquation).normalized()) - , d(planeEquation.w() / Vector3D(planeEquation).length()) - {} - - const Vector4D planeEquation; - const Vector3D normal; - const float d; -}; - -struct Q_AUTOTEST_EXPORT ClearBufferInfo -{ - int drawBufferIndex = 0; - QRenderTargetOutput::AttachmentPoint attchmentPoint = QRenderTargetOutput::Color0; - QVector4D clearColor; -}; - -struct Q_AUTOTEST_EXPORT BlitFramebufferInfo -{ - Qt3DCore::QNodeId sourceRenderTargetId; - Qt3DCore::QNodeId destinationRenderTargetId; - QRect sourceRect; - QRect destinationRect; - Qt3DRender::QRenderTargetOutput::AttachmentPoint sourceAttachmentPoint; - Qt3DRender::QRenderTargetOutput::AttachmentPoint destinationAttachmentPoint; - QBlitFramebuffer::InterpolationMethod interpolationMethod; -}; - -// This class is kind of analogous to RenderBin but I want to avoid trampling -// on that until we get this working - -class Q_AUTOTEST_EXPORT RenderView -{ -public: - RenderView(); - ~RenderView(); - - QT3D_ALIGNED_MALLOC_AND_FREE() - - // TODO: Add a way to specify a sort predicate for the RenderCommands - void sort(); - - void setRenderer(Renderer *renderer); - inline void setSurfaceSize(const QSize &size) Q_DECL_NOTHROW { m_surfaceSize = size; } - inline Renderer *renderer() const Q_DECL_NOTHROW { return m_renderer; } - inline NodeManagers *nodeManagers() const Q_DECL_NOTHROW { return m_manager; } - inline const QSize &surfaceSize() const Q_DECL_NOTHROW { return m_surfaceSize; } - inline void setDevicePixelRatio(qreal r) Q_DECL_NOTHROW { m_devicePixelRatio = r; } - inline qreal devicePixelRatio() const Q_DECL_NOTHROW { return m_devicePixelRatio; } - - inline void setRenderCameraLens(CameraLens *renderCameraLens) Q_DECL_NOTHROW { m_data.m_renderCameraLens = renderCameraLens; } - inline CameraLens *renderCameraLens() const Q_DECL_NOTHROW { return m_data.m_renderCameraLens; } - - inline void setRenderCameraEntity(Entity *renderCameraNode) Q_DECL_NOTHROW { m_data.m_renderCameraNode = renderCameraNode; } - inline Entity *renderCameraEntity() const Q_DECL_NOTHROW { return m_data.m_renderCameraNode; } - - inline void setViewMatrix(const Matrix4x4 &viewMatrix) Q_DECL_NOTHROW { m_data.m_viewMatrix = viewMatrix; } - inline Matrix4x4 viewMatrix() const Q_DECL_NOTHROW { return m_data.m_viewMatrix; } - - inline void setViewProjectionMatrix(const Matrix4x4 &viewProjectionMatrix) Q_DECL_NOTHROW { m_data.m_viewProjectionMatrix = viewProjectionMatrix; } - inline Matrix4x4 viewProjectionMatrix() const Q_DECL_NOTHROW { return m_data.m_viewProjectionMatrix; } - - inline void setEyePosition(const Vector3D &eyePos) Q_DECL_NOTHROW { m_data.m_eyePos = eyePos; } - inline Vector3D eyePosition() const Q_DECL_NOTHROW { return m_data.m_eyePos; } - - inline void setEyeViewDirection(const Vector3D &dir) Q_DECL_NOTHROW { m_data.m_eyeViewDir = dir; } - inline Vector3D eyeViewDirection() const Q_DECL_NOTHROW { return m_data.m_eyeViewDir; } - - inline void appendLayerFilter(const Qt3DCore::QNodeId layerFilterId) Q_DECL_NOTHROW { m_data.m_layerFilterIds.push_back(layerFilterId); } - inline Qt3DCore::QNodeIdVector layerFilters() const Q_DECL_NOTHROW { return m_data.m_layerFilterIds; } - - inline void appendProximityFilterId(const Qt3DCore::QNodeId proximityFilterId) { m_data.m_proximityFilterIds.push_back(proximityFilterId); } - inline Qt3DCore::QNodeIdVector proximityFilterIds() const { return m_data.m_proximityFilterIds; } - - inline void setRenderPassFilter(const RenderPassFilter *rpFilter) Q_DECL_NOTHROW { m_data.m_passFilter = rpFilter; } - inline const RenderPassFilter *renderPassFilter() const Q_DECL_NOTHROW { return m_data.m_passFilter; } - - inline void setTechniqueFilter(const TechniqueFilter *filter) Q_DECL_NOTHROW { m_data.m_techniqueFilter = filter; } - inline const TechniqueFilter *techniqueFilter() const Q_DECL_NOTHROW { return m_data.m_techniqueFilter; } - - inline RenderStateSet *stateSet() const Q_DECL_NOTHROW { return m_stateSet; } - void setStateSet(RenderStateSet *stateSet) Q_DECL_NOTHROW { m_stateSet = stateSet; } - - inline bool noDraw() const Q_DECL_NOTHROW { return m_noDraw; } - void setNoDraw(bool noDraw) Q_DECL_NOTHROW { m_noDraw = noDraw; } - - inline bool isCompute() const Q_DECL_NOTHROW { return m_compute; } - void setCompute(bool compute) Q_DECL_NOTHROW { m_compute = compute; } - - void setComputeWorkgroups(int x, int y, int z) Q_DECL_NOTHROW { m_workGroups[0] = x; m_workGroups[1] = y; m_workGroups[2] = z; } - const int *computeWorkGroups() const Q_DECL_NOTHROW { return m_workGroups; } - inline bool frustumCulling() const Q_DECL_NOTHROW { return m_frustumCulling; } - void setFrustumCulling(bool frustumCulling) Q_DECL_NOTHROW { m_frustumCulling = frustumCulling; } - - inline void setMaterialParameterTable(const MaterialParameterGathererData ¶meters) Q_DECL_NOTHROW { m_parameters = parameters; } - - // 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) Q_DECL_NOTHROW { m_viewport = vp; } - inline QRectF viewport() const Q_DECL_NOTHROW { return m_viewport; } - - inline float gamma() const Q_DECL_NOTHROW { return m_gamma; } - inline void setGamma(float gamma) Q_DECL_NOTHROW { m_gamma = gamma; } - - // depth and stencil ClearBuffers are cached locally - // color ClearBuffers are collected, as there may be multiple - // color buffers to be cleared. we need to apply all these at rendering - void addClearBuffers(const ClearBuffers *cb); - inline QVector<ClearBufferInfo> specificClearColorBufferInfo() const { return m_specificClearColorBuffers; } - inline QVector<ClearBufferInfo> &specificClearColorBufferInfo() { return m_specificClearColorBuffers; } - inline ClearBufferInfo globalClearColorBufferInfo() const { return m_globalClearColorBuffer; } - - inline QClearBuffers::BufferTypeFlags clearTypes() const { return m_clearBuffer; } - inline float clearDepthValue() const { return m_clearDepthValue; } - inline int clearStencilValue() const { return m_clearStencilValue; } - - RenderPassList passesAndParameters(ParameterInfoList *parameter, Entity *node, bool useDefaultMaterials = true); - - QVector<RenderCommand *> buildDrawRenderCommands(const QVector<Entity *> &entities) const; - QVector<RenderCommand *> buildComputeRenderCommands(const QVector<Entity *> &entities) const; - void setCommands(QVector<RenderCommand *> &commands) Q_DECL_NOTHROW { m_commands = commands; } - QVector<RenderCommand *> commands() const Q_DECL_NOTHROW { return m_commands; } - - void setAttachmentPack(const AttachmentPack &pack) { m_attachmentPack = pack; } - const AttachmentPack &attachmentPack() const { return m_attachmentPack; } - - void setRenderTargetId(Qt3DCore::QNodeId renderTargetId) Q_DECL_NOTHROW { m_renderTarget = renderTargetId; } - Qt3DCore::QNodeId renderTargetId() const Q_DECL_NOTHROW { return m_renderTarget; } - - void addSortType(const QVector<Qt3DRender::QSortPolicy::SortType> &sortTypes) { m_data.m_sortingTypes.append(sortTypes); } - - void setSurface(QSurface *surface) { m_surface = surface; } - QSurface *surface() const { return m_surface; } - - void setLightSources(const QVector<LightSource> &lightSources) Q_DECL_NOTHROW { m_lightSources = lightSources; } - void setEnvironmentLight(EnvironmentLight *environmentLight) Q_DECL_NOTHROW { m_environmentLight = environmentLight; } - - void updateMatrices(); - - inline void setRenderCaptureNodeId(const Qt3DCore::QNodeId nodeId) Q_DECL_NOTHROW { m_renderCaptureNodeId = nodeId; } - inline const Qt3DCore::QNodeId renderCaptureNodeId() const Q_DECL_NOTHROW { return m_renderCaptureNodeId; } - inline void setRenderCaptureRequest(const QRenderCaptureRequest& request) Q_DECL_NOTHROW { m_renderCaptureRequest = request; } - inline const QRenderCaptureRequest renderCaptureRequest() const Q_DECL_NOTHROW { return m_renderCaptureRequest; } - - void setMemoryBarrier(QMemoryBarrier::Operations barrier) Q_DECL_NOTHROW { m_memoryBarrier = barrier; } - QMemoryBarrier::Operations memoryBarrier() const Q_DECL_NOTHROW { return m_memoryBarrier; } - - // Helps making the size of RenderView smaller - // Contains all the data needed for the actual building of the RenderView - // But that aren't used later by the Renderer - struct InnerData { - InnerData() - : m_renderCameraLens(nullptr) - , m_renderCameraNode(nullptr) - , m_techniqueFilter(nullptr) - , m_passFilter(nullptr) - { - } - CameraLens *m_renderCameraLens; - Entity *m_renderCameraNode; - const TechniqueFilter *m_techniqueFilter; - const RenderPassFilter *m_passFilter; - Matrix4x4 m_viewMatrix; - Matrix4x4 m_viewProjectionMatrix; - Qt3DCore::QNodeIdVector m_layerFilterIds; - QVector<Qt3DRender::QSortPolicy::SortType> m_sortingTypes; - Vector3D m_eyePos; - Vector3D m_eyeViewDir; - Qt3DCore::QNodeIdVector m_proximityFilterIds; - }; - - bool isDownloadBuffersEnable() const; - void setIsDownloadBuffersEnable(bool isDownloadBuffersEnable); - - BlitFramebufferInfo blitFrameBufferInfo() const; - void setBlitFrameBufferInfo(const BlitFramebufferInfo &blitFrameBufferInfo); - - bool hasBlitFramebufferInfo() const; - void setHasBlitFramebufferInfo(bool hasBlitFramebufferInfo); - -private: - void setShaderAndUniforms(RenderCommand *command, - RenderPass *pass, - ParameterInfoList ¶meters, - Entity *entity, - const QVector<LightSource> &activeLightSources, - EnvironmentLight *environmentLight) const; - mutable QThreadStorage<UniformBlockValueBuilder*> m_localData; - - Qt3DCore::QNodeId m_renderCaptureNodeId; - QRenderCaptureRequest m_renderCaptureRequest; - bool m_isDownloadBuffersEnable; - - bool m_hasBlitFramebufferInfo; - BlitFramebufferInfo m_blitFrameBufferInfo; - - Renderer *m_renderer; - NodeManagers *m_manager; - QSize m_surfaceSize; - qreal m_devicePixelRatio; - - InnerData m_data; - - QRectF m_viewport; - float m_gamma; - Qt3DCore::QNodeId m_renderTarget; - QSurface *m_surface; - AttachmentPack m_attachmentPack; - QClearBuffers::BufferTypeFlags m_clearBuffer; - float m_clearDepthValue; - int m_clearStencilValue; - ClearBufferInfo m_globalClearColorBuffer; // global ClearColor - QVector<ClearBufferInfo> m_specificClearColorBuffers; // different draw buffers with distinct colors - RenderStateSet *m_stateSet; - bool m_noDraw:1; - bool m_compute:1; - bool m_frustumCulling:1; - int m_workGroups[3]; - QMemoryBarrier::Operations m_memoryBarrier; - - // 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. - QVector<RenderCommand *> m_commands; - mutable QVector<LightSource> m_lightSources; - EnvironmentLight *m_environmentLight; - - MaterialParameterGathererData m_parameters; - - enum StandardUniform - { - ModelMatrix, - ViewMatrix, - ProjectionMatrix, - ModelViewMatrix, - ViewProjectionMatrix, - ModelViewProjectionMatrix, - InverseModelMatrix, - InverseViewMatrix, - InverseProjectionMatrix, - InverseModelViewMatrix, - InverseViewProjectionMatrix, - InverseModelViewProjectionMatrix, - ModelNormalMatrix, - ModelViewNormalMatrix, - ViewportMatrix, - InverseViewportMatrix, - AspectRatio, - Time, - Exposure, - Gamma, - EyePosition, - SkinningPalette - }; - - typedef QHash<int, StandardUniform> StandardUniformsNameToTypeHash; - static StandardUniformsNameToTypeHash ms_standardUniformSetters; - static StandardUniformsNameToTypeHash initializeStandardUniformSetters(); - - UniformValue standardUniformValue(StandardUniform standardUniformType, - Entity *entity, - const Matrix4x4 &model) const; - - void setUniformValue(ShaderParameterPack &uniformPack, int nameId, const UniformValue &value) const; - void setStandardUniformValue(ShaderParameterPack &uniformPack, - int glslNameId, - int nameId, - Entity *entity, - const Matrix4x4 &worldTransform) const; - void setUniformBlockValue(ShaderParameterPack &uniformPack, - Shader *shader, - const ShaderUniformBlock &block, - const UniformValue &value) const; - void setShaderStorageValue(ShaderParameterPack &uniformPack, - Shader *shader, - const ShaderStorageBlock &block, - const UniformValue &value) const; - void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, - Shader *shader, - ShaderData *shaderData, - const QString &structName) const; -}; - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERVIEW_H diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp deleted file mode 100644 index d08bd6dd4..000000000 --- a/src/render/backend/renderviewbuilder.cpp +++ /dev/null @@ -1,672 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "renderviewbuilder_p.h" - -#include <QThread> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -const int RenderViewBuilder::m_optimalParallelJobCount = std::max(QThread::idealThreadCount(), 2); - -namespace { - -class SyncRenderViewCommandBuilders -{ -public: - explicit SyncRenderViewCommandBuilders(const RenderViewInitializerJobPtr &renderViewJob, - const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs, - Renderer *renderer) - : m_renderViewJob(renderViewJob) - , m_renderViewBuilderJobs(renderViewBuilderJobs) - , m_renderer(renderer) - {} - - void operator()() - { - // Append all the commands and sort them - RenderView *rv = m_renderViewJob->renderView(); - - int totalCommandCount = 0; - for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) - totalCommandCount += renderViewCommandBuilder->commands().size(); - - QVector<RenderCommand *> commands; - commands.reserve(totalCommandCount); - - // Reduction - for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) - commands += std::move(renderViewCommandBuilder->commands()); - rv->setCommands(commands); - - // Sort the commands - rv->sort(); - - // Enqueue our fully populated RenderView with the RenderThread - m_renderer->enqueueRenderView(rv, m_renderViewJob->submitOrderIndex()); - } - -private: - RenderViewInitializerJobPtr m_renderViewJob; - QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; - Renderer *m_renderer; -}; - -class SyncFrustumCulling -{ -public: - explicit SyncFrustumCulling(const RenderViewInitializerJobPtr &renderViewJob, - const FrustumCullingJobPtr &frustumCulling) - : m_renderViewJob(renderViewJob) - , m_frustumCullingJob(frustumCulling) - {} - - void operator()() - { - RenderView *rv = m_renderViewJob->renderView(); - - // Update matrices now that all transforms have been updated - rv->updateMatrices(); - - // Frustum culling - m_frustumCullingJob->setViewProjection(rv->viewProjectionMatrix()); - } - -private: - RenderViewInitializerJobPtr m_renderViewJob; - FrustumCullingJobPtr m_frustumCullingJob; -}; - -class SyncRenderViewInitialization -{ -public: - explicit SyncRenderViewInitialization(const RenderViewInitializerJobPtr &renderViewJob, - const FrustumCullingJobPtr &frustumCullingJob, - const FilterLayerEntityJobPtr &filterEntityByLayerJob, - const FilterProximityDistanceJobPtr &filterProximityJob, - const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs, - const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs) - : m_renderViewJob(renderViewJob) - , m_frustumCullingJob(frustumCullingJob) - , m_filterEntityByLayerJob(filterEntityByLayerJob) - , m_filterProximityJob(filterProximityJob) - , m_materialGathererJobs(materialGathererJobs) - , m_renderViewBuilderJobs(renderViewBuilderJobs) - {} - - void operator()() - { - RenderView *rv = m_renderViewJob->renderView(); - - // Layer filtering - if (!m_filterEntityByLayerJob.isNull()) - m_filterEntityByLayerJob->setLayerFilters(rv->layerFilters()); - - // Proximity filtering - m_filterProximityJob->setProximityFilterIds(rv->proximityFilterIds()); - - // Material Parameter building - for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) { - materialGatherer->setRenderPassFilter(const_cast<RenderPassFilter *>(rv->renderPassFilter())); - materialGatherer->setTechniqueFilter(const_cast<TechniqueFilter *>(rv->techniqueFilter())); - } - - // Command builders - for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) - renderViewCommandBuilder->setRenderView(rv); - - // Set whether frustum culling is enabled or not - m_frustumCullingJob->setActive(rv->frustumCulling()); - } - -private: - RenderViewInitializerJobPtr m_renderViewJob; - FrustumCullingJobPtr m_frustumCullingJob; - FilterLayerEntityJobPtr m_filterEntityByLayerJob; - FilterProximityDistanceJobPtr m_filterProximityJob; - QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; - QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; -}; - -class SyncRenderCommandBuilding -{ -public: - explicit SyncRenderCommandBuilding(const RenderViewInitializerJobPtr &renderViewJob, - const FrustumCullingJobPtr &frustumCullingJob, - const FilterProximityDistanceJobPtr &filterProximityJob, - const LightGathererPtr &lightGathererJob, - const RenderableEntityFilterPtr &renderableEntityFilterJob, - const ComputableEntityFilterPtr &computableEntityFilterJob, - const QVector<MaterialParameterGathererJobPtr> &materialGathererJobs, - const QVector<RenderViewBuilderJobPtr> &renderViewBuilderJobs, - Renderer *renderer, - FrameGraphNode *leafNode) - : m_renderViewJob(renderViewJob) - , m_frustumCullingJob(frustumCullingJob) - , m_filterProximityJob(filterProximityJob) - , m_lightGathererJob(lightGathererJob) - , m_renderableEntityFilterJob(renderableEntityFilterJob) - , m_computableEntityFilterJob(computableEntityFilterJob) - , m_materialGathererJobs(materialGathererJobs) - , m_renderViewBuilderJobs(renderViewBuilderJobs) - , m_renderer(renderer) - , m_leafNode(leafNode) - {} - - void operator()() - { - // Set the result of previous job computations - // for final RenderCommand building - RenderView *rv = m_renderViewJob->renderView(); - - if (!rv->noDraw()) { - rv->setEnvironmentLight(m_lightGathererJob->takeEnvironmentLight()); - - // We sort the vector so that the removal can then be performed linearly - - QVector<Entity *> renderableEntities; - const bool isDraw = !rv->isCompute(); - if (isDraw) - renderableEntities = std::move(m_renderableEntityFilterJob->filteredEntities()); - else - renderableEntities = std::move(m_computableEntityFilterJob->filteredEntities()); - - // Filter out entities that weren't selected by the layer filters - std::sort(renderableEntities.begin(), renderableEntities.end()); - - QMutexLocker lock(m_renderer->cache()->mutex()); - const QVector<Entity *> filteredEntities = m_renderer->cache()->leafNodeCache.value(m_leafNode).filterEntitiesByLayer; - lock.unlock(); - // Remove all entities from the compute and renderable vectors that aren't in the filtered layer vector - renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, filteredEntities); - - // Set the light sources, with layer filters applied. - QVector<LightSource> lightSources = m_lightGathererJob->lights(); - for (int i = 0; i < lightSources.count(); ++i) { - if (!filteredEntities.contains(lightSources[i].entity)) - lightSources.removeAt(i--); - } - rv->setLightSources(lightSources); - - if (isDraw) { - // Filter out frustum culled entity for drawable entities - if (rv->frustumCulling()) - renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_frustumCullingJob->visibleEntities()); - // Filter out entities which didn't satisfy proximity filtering - renderableEntities = RenderViewBuilder::entitiesInSubset(renderableEntities, m_filterProximityJob->filteredEntities()); - } - - // Split among the number of command builders - int i = 0; - const int m = RenderViewBuilder::optimalJobCount() - 1; - const int packetSize = renderableEntities.size() / RenderViewBuilder::optimalJobCount(); - while (i < m) { - const RenderViewBuilderJobPtr renderViewCommandBuilder = m_renderViewBuilderJobs.at(i); - renderViewCommandBuilder->setRenderables(renderableEntities.mid(i * packetSize, packetSize)); - ++i; - } - m_renderViewBuilderJobs.at(i)->setRenderables(renderableEntities.mid(i * packetSize, packetSize + renderableEntities.size() % (m + 1))); - { - QMutexLocker rendererCacheLock(m_renderer->cache()->mutex()); - rv->setMaterialParameterTable(m_renderer->cache()->leafNodeCache.value(m_leafNode).materialParameterGatherer); - } - } - } - -private: - RenderViewInitializerJobPtr m_renderViewJob; - FrustumCullingJobPtr m_frustumCullingJob; - FilterProximityDistanceJobPtr m_filterProximityJob; - LightGathererPtr m_lightGathererJob; - RenderableEntityFilterPtr m_renderableEntityFilterJob; - ComputableEntityFilterPtr m_computableEntityFilterJob; - QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; - QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; - Renderer *m_renderer; - FrameGraphNode *m_leafNode; -}; - -class SetClearDrawBufferIndex -{ -public: - explicit SetClearDrawBufferIndex(const RenderViewInitializerJobPtr &renderViewJob) - : m_renderViewJob(renderViewJob) - {} - - void operator()() - { - RenderView *rv = m_renderViewJob->renderView(); - QVector<ClearBufferInfo> &clearBuffersInfo = rv->specificClearColorBufferInfo(); - const AttachmentPack &attachmentPack = rv->attachmentPack(); - for (ClearBufferInfo &clearBufferInfo : clearBuffersInfo) - clearBufferInfo.drawBufferIndex = attachmentPack.getDrawBufferIndex(clearBufferInfo.attchmentPoint); - - } - -private: - RenderViewInitializerJobPtr m_renderViewJob; -}; - -class SyncFilterEntityByLayer -{ -public: - explicit SyncFilterEntityByLayer(const FilterLayerEntityJobPtr &filterEntityByLayerJob, - Renderer *renderer, - FrameGraphNode *leafNode) - : m_filterEntityByLayerJob(filterEntityByLayerJob) - , m_renderer(renderer) - , m_leafNode(leafNode) - { - } - - void operator()() - { - QMutexLocker lock(m_renderer->cache()->mutex()); - // Save the filtered by layer subset into the cache - const QVector<Entity *> filteredEntities = m_filterEntityByLayerJob->filteredEntities(); - RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; - dataCacheForLeaf.filterEntitiesByLayer = filteredEntities; - } - -private: - FilterLayerEntityJobPtr m_filterEntityByLayerJob; - Renderer *m_renderer; - FrameGraphNode *m_leafNode; -}; - -class SyncMaterialParameterGatherer -{ -public: - explicit SyncMaterialParameterGatherer(const QVector<MaterialParameterGathererJobPtr> &materialParameterGathererJobs, - Renderer *renderer, - FrameGraphNode *leafNode) - : m_materialParameterGathererJobs(materialParameterGathererJobs) - , m_renderer(renderer) - , m_leafNode(leafNode) - { - } - - void operator()() - { - QMutexLocker lock(m_renderer->cache()->mutex()); - RendererCache::LeafNodeData &dataCacheForLeaf = m_renderer->cache()->leafNodeCache[m_leafNode]; - dataCacheForLeaf.materialParameterGatherer.clear(); - - for (const auto &materialGatherer : qAsConst(m_materialParameterGathererJobs)) - dataCacheForLeaf.materialParameterGatherer.unite(materialGatherer->materialToPassAndParameter()); - } - -private: - QVector<MaterialParameterGathererJobPtr> m_materialParameterGathererJobs; - Renderer *m_renderer; - FrameGraphNode *m_leafNode; -}; - -} // anonymous - -RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer) - : m_leafNode(leafNode) - , m_renderViewIndex(renderViewIndex) - , m_renderer(renderer) - , m_layerCacheNeedsToBeRebuilt(false) - , m_materialGathererCacheNeedsToBeRebuilt(false) - , m_renderViewJob(RenderViewInitializerJobPtr::create()) - , m_filterEntityByLayerJob() - , m_lightGathererJob(Render::LightGathererPtr::create()) - , m_renderableEntityFilterJob(RenderableEntityFilterPtr::create()) - , m_computableEntityFilterJob(ComputableEntityFilterPtr::create()) - , m_frustumCullingJob(new Render::FrustumCullingJob()) - , m_syncFrustumCullingJob(SynchronizerJobPtr::create(SyncFrustumCulling(m_renderViewJob, m_frustumCullingJob), JobTypes::SyncFrustumCulling)) - , m_setClearDrawBufferIndexJob(SynchronizerJobPtr::create(SetClearDrawBufferIndex(m_renderViewJob), JobTypes::ClearBufferDrawIndex)) - , m_syncFilterEntityByLayerJob() - , m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create()) -{ -} - -RenderViewInitializerJobPtr RenderViewBuilder::renderViewJob() const -{ - return m_renderViewJob; -} - -FilterLayerEntityJobPtr RenderViewBuilder::filterEntityByLayerJob() const -{ - return m_filterEntityByLayerJob; -} - -LightGathererPtr RenderViewBuilder::lightGathererJob() const -{ - return m_lightGathererJob; -} - -RenderableEntityFilterPtr RenderViewBuilder::renderableEntityFilterJob() const -{ - return m_renderableEntityFilterJob; -} - -ComputableEntityFilterPtr RenderViewBuilder::computableEntityFilterJob() const -{ - return m_computableEntityFilterJob; -} - -FrustumCullingJobPtr RenderViewBuilder::frustumCullingJob() const -{ - return m_frustumCullingJob; -} - -QVector<RenderViewBuilderJobPtr> RenderViewBuilder::renderViewBuilderJobs() const -{ - return m_renderViewBuilderJobs; -} - -QVector<MaterialParameterGathererJobPtr> RenderViewBuilder::materialGathererJobs() const -{ - return m_materialGathererJobs; -} - -SynchronizerJobPtr RenderViewBuilder::syncRenderViewInitializationJob() const -{ - return m_syncRenderViewInitializationJob; -} - -SynchronizerJobPtr RenderViewBuilder::syncFrustumCullingJob() const -{ - return m_syncFrustumCullingJob; -} - -SynchronizerJobPtr RenderViewBuilder::syncRenderCommandBuildingJob() const -{ - return m_syncRenderCommandBuildingJob; -} - -SynchronizerJobPtr RenderViewBuilder::syncRenderViewCommandBuildersJob() const -{ - return m_syncRenderViewCommandBuildersJob; -} - -SynchronizerJobPtr RenderViewBuilder::setClearDrawBufferIndexJob() const -{ - return m_setClearDrawBufferIndexJob; -} - -SynchronizerJobPtr RenderViewBuilder::syncFilterEntityByLayerJob() const -{ - return m_syncFilterEntityByLayerJob; -} - -SynchronizerJobPtr RenderViewBuilder::syncMaterialGathererJob() const -{ - return m_syncMaterialGathererJob; -} - -FilterProximityDistanceJobPtr RenderViewBuilder::filterProximityJob() const -{ - return m_filterProximityJob; -} - -void RenderViewBuilder::prepareJobs() -{ - // Init what we can here - EntityManager *entityManager = m_renderer->nodeManagers()->renderNodesManager(); - m_filterProximityJob->setManager(m_renderer->nodeManagers()); - m_renderableEntityFilterJob->setManager(entityManager); - m_computableEntityFilterJob->setManager(entityManager); - m_frustumCullingJob->setRoot(m_renderer->sceneRoot()); - m_lightGathererJob->setManager(entityManager); - m_renderViewJob->setRenderer(m_renderer); - m_renderViewJob->setFrameGraphLeafNode(m_leafNode); - m_renderViewJob->setSubmitOrderIndex(m_renderViewIndex); - - // RenderCommand building is the most consuming task -> split it - // Estimate the number of jobs to create based on the number of entities - m_renderViewBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount); - for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) { - auto renderViewCommandBuilder = Render::RenderViewBuilderJobPtr::create(); - renderViewCommandBuilder->setIndex(m_renderViewIndex); - renderViewCommandBuilder->setRenderer(m_renderer); - m_renderViewBuilderJobs.push_back(renderViewCommandBuilder); - } - - if (m_materialGathererCacheNeedsToBeRebuilt) { - // Since Material gathering is an heavy task, we split it - const QVector<HMaterial> materialHandles = m_renderer->nodeManagers()->materialManager()->activeHandles(); - const int elementsPerJob = materialHandles.size() / RenderViewBuilder::m_optimalParallelJobCount; - const int lastRemaingElements = materialHandles.size() % RenderViewBuilder::m_optimalParallelJobCount; - m_materialGathererJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount); - for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) { - auto materialGatherer = Render::MaterialParameterGathererJobPtr::create(); - materialGatherer->setNodeManagers(m_renderer->nodeManagers()); - materialGatherer->setRenderer(m_renderer); - if (i == RenderViewBuilder::m_optimalParallelJobCount - 1) - materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob + lastRemaingElements)); - else - materialGatherer->setHandles(materialHandles.mid(i * elementsPerJob, elementsPerJob)); - m_materialGathererJobs.push_back(materialGatherer); - } - m_syncMaterialGathererJob = SynchronizerJobPtr::create(SyncMaterialParameterGatherer(m_materialGathererJobs, - m_renderer, - m_leafNode), - JobTypes::SyncMaterialGatherer); - } - - if (m_layerCacheNeedsToBeRebuilt) { - m_filterEntityByLayerJob = Render::FilterLayerEntityJobPtr::create(); - m_filterEntityByLayerJob->setManager(m_renderer->nodeManagers()); - m_syncFilterEntityByLayerJob = SynchronizerJobPtr::create(SyncFilterEntityByLayer(m_filterEntityByLayerJob, - m_renderer, - m_leafNode), - JobTypes::SyncFilterEntityByLayer); - } - - m_syncRenderCommandBuildingJob = SynchronizerJobPtr::create(SyncRenderCommandBuilding(m_renderViewJob, - m_frustumCullingJob, - m_filterProximityJob, - m_lightGathererJob, - m_renderableEntityFilterJob, - m_computableEntityFilterJob, - m_materialGathererJobs, - m_renderViewBuilderJobs, - m_renderer, - m_leafNode), - JobTypes::SyncRenderViewCommandBuilding); - - m_syncRenderViewCommandBuildersJob = SynchronizerJobPtr::create(SyncRenderViewCommandBuilders(m_renderViewJob, - m_renderViewBuilderJobs, - m_renderer), - JobTypes::SyncRenderViewCommandBuilder); - - m_syncRenderViewInitializationJob = SynchronizerJobPtr::create(SyncRenderViewInitialization(m_renderViewJob, - m_frustumCullingJob, - m_filterEntityByLayerJob, - m_filterProximityJob, - m_materialGathererJobs, - m_renderViewBuilderJobs), - JobTypes::SyncRenderViewInitialization); - -} - -QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const -{ - QVector<Qt3DCore::QAspectJobPtr> jobs; - - jobs.reserve(m_materialGathererJobs.size() + m_renderViewBuilderJobs.size() + 11); - - // Set dependencies - - // Finish the skinning palette job before processing renderviews - // TODO: Maybe only update skinning palettes for non-culled entities - m_renderViewJob->addDependency(m_renderer->updateSkinningPaletteJob()); - - m_syncFrustumCullingJob->addDependency(m_renderer->updateWorldTransformJob()); - m_syncFrustumCullingJob->addDependency(m_renderer->updateShaderDataTransformJob()); - m_syncFrustumCullingJob->addDependency(m_syncRenderViewInitializationJob); - - m_frustumCullingJob->addDependency(m_renderer->expandBoundingVolumeJob()); - m_frustumCullingJob->addDependency(m_syncFrustumCullingJob); - - m_setClearDrawBufferIndexJob->addDependency(m_syncRenderViewInitializationJob); - - m_syncRenderViewInitializationJob->addDependency(m_renderViewJob); - - m_filterProximityJob->addDependency(m_renderer->expandBoundingVolumeJob()); - m_filterProximityJob->addDependency(m_syncRenderViewInitializationJob); - - m_syncRenderCommandBuildingJob->addDependency(m_syncRenderViewInitializationJob); - m_syncRenderCommandBuildingJob->addDependency(m_renderableEntityFilterJob); - m_syncRenderCommandBuildingJob->addDependency(m_computableEntityFilterJob); - m_syncRenderCommandBuildingJob->addDependency(m_filterProximityJob); - m_syncRenderCommandBuildingJob->addDependency(m_lightGathererJob); - m_syncRenderCommandBuildingJob->addDependency(m_frustumCullingJob); - - // Ensure the RenderThread won't be able to process dirtyResources - // before they have been completely gathered - m_syncRenderCommandBuildingJob->addDependency(m_renderer->introspectShadersJob()); - m_syncRenderCommandBuildingJob->addDependency(m_renderer->bufferGathererJob()); - m_syncRenderCommandBuildingJob->addDependency(m_renderer->textureGathererJob()); - - for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) { - renderViewCommandBuilder->addDependency(m_syncRenderCommandBuildingJob); - m_syncRenderViewCommandBuildersJob->addDependency(renderViewCommandBuilder); - } - - m_renderer->frameCleanupJob()->addDependency(m_syncRenderViewCommandBuildersJob); - m_renderer->frameCleanupJob()->addDependency(m_setClearDrawBufferIndexJob); - - // Add jobs - jobs.push_back(m_renderViewJob); // Step 1 - jobs.push_back(m_renderableEntityFilterJob); // Step 1 - jobs.push_back(m_lightGathererJob); // Step 1 - - // Note: do it only if OpenGL 4.3+ available - jobs.push_back(m_computableEntityFilterJob); // Step 1 - - jobs.push_back(m_syncRenderViewInitializationJob); // Step 2 - - if (m_layerCacheNeedsToBeRebuilt) { - m_filterEntityByLayerJob->addDependency(m_syncRenderViewInitializationJob); - m_filterEntityByLayerJob->addDependency(m_renderer->updateTreeEnabledJob()); - - m_syncFilterEntityByLayerJob->addDependency(m_filterEntityByLayerJob); - m_syncRenderCommandBuildingJob->addDependency(m_syncFilterEntityByLayerJob); - - jobs.push_back(m_filterEntityByLayerJob); // Step 3 - jobs.push_back(m_syncFilterEntityByLayerJob); // Step 4 - } - jobs.push_back(m_syncFrustumCullingJob); // Step 3 - jobs.push_back(m_filterProximityJob); // Step 3 - jobs.push_back(m_setClearDrawBufferIndexJob); // Step 3 - - if (m_materialGathererCacheNeedsToBeRebuilt) { - for (const auto &materialGatherer : qAsConst(m_materialGathererJobs)) { - materialGatherer->addDependency(m_syncRenderViewInitializationJob); - materialGatherer->addDependency(m_renderer->introspectShadersJob()); - materialGatherer->addDependency(m_renderer->filterCompatibleTechniqueJob()); - jobs.push_back(materialGatherer); // Step3 - m_syncMaterialGathererJob->addDependency(materialGatherer); - } - m_syncRenderCommandBuildingJob->addDependency(m_syncMaterialGathererJob); - - jobs.push_back(m_syncMaterialGathererJob); // Step 3 - } - - jobs.push_back(m_frustumCullingJob); // Step 4 - jobs.push_back(m_syncRenderCommandBuildingJob); // Step 5 - - for (const auto &renderViewCommandBuilder : qAsConst(m_renderViewBuilderJobs)) // Step 6 - jobs.push_back(renderViewCommandBuilder); - - jobs.push_back(m_syncRenderViewCommandBuildersJob); // Step 7 - - return jobs; -} - -Renderer *RenderViewBuilder::renderer() const -{ - return m_renderer; -} - -int RenderViewBuilder::renderViewIndex() const -{ - return m_renderViewIndex; -} - -void RenderViewBuilder::setLayerCacheNeedsToBeRebuilt(bool needsToBeRebuilt) -{ - m_layerCacheNeedsToBeRebuilt = needsToBeRebuilt; -} - -bool RenderViewBuilder::layerCacheNeedsToBeRebuilt() const -{ - return m_layerCacheNeedsToBeRebuilt; -} - -void RenderViewBuilder::setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt) -{ - m_materialGathererCacheNeedsToBeRebuilt = needsToBeRebuilt; -} - -bool RenderViewBuilder::materialGathererCacheNeedsToBeRebuilt() const -{ - return m_materialGathererCacheNeedsToBeRebuilt; -} - -int RenderViewBuilder::optimalJobCount() -{ - return RenderViewBuilder::m_optimalParallelJobCount; -} - -QVector<Entity *> RenderViewBuilder::entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset) -{ - QVector<Entity *> intersection; - intersection.reserve(qMin(entities.size(), subset.size())); - std::set_intersection(entities.begin(), entities.end(), - subset.begin(), subset.end(), - std::back_inserter(intersection)); - - return intersection; -} - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/renderviewbuilder_p.h b/src/render/backend/renderviewbuilder_p.h deleted file mode 100644 index 818313500..000000000 --- a/src/render/backend/renderviewbuilder_p.h +++ /dev/null @@ -1,149 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_RENDERVIEWBUILDER_H -#define QT3DRENDER_RENDER_RENDERVIEWBUILDER_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <functional> -#include <Qt3DCore/qaspectjob.h> -#include <Qt3DRender/private/filterentitybycomponentjob_p.h> -#include <Qt3DRender/private/filterlayerentityjob_p.h> -#include <Qt3DRender/private/genericlambdajob_p.h> -#include <Qt3DRender/private/materialparametergathererjob_p.h> -#include <Qt3DRender/private/nodemanagers_p.h> -#include <Qt3DRender/private/renderviewbuilderjob_p.h> -#include <Qt3DRender/private/renderview_p.h> -#include <Qt3DRender/private/frustumcullingjob_p.h> -#include <Qt3DRender/private/lightgatherer_p.h> -#include <Qt3DRender/private/filterproximitydistancejob_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -class Renderer; - -using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>; -using ComputableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::ComputeCommand, Render::Material>; -using RenderableEntityFilterPtr = FilterEntityByComponentJobPtr<Render::GeometryRenderer, Render::Material>; - -class Q_AUTOTEST_EXPORT RenderViewBuilder -{ -public: - explicit RenderViewBuilder(Render::FrameGraphNode *leafNode, int renderViewIndex, Renderer *renderer); - - RenderViewInitializerJobPtr renderViewJob() const; - FilterLayerEntityJobPtr filterEntityByLayerJob() const; - LightGathererPtr lightGathererJob() const; - RenderableEntityFilterPtr renderableEntityFilterJob() const; - ComputableEntityFilterPtr computableEntityFilterJob() const; - FrustumCullingJobPtr frustumCullingJob() const; - QVector<RenderViewBuilderJobPtr> renderViewBuilderJobs() const; - QVector<MaterialParameterGathererJobPtr> materialGathererJobs() const; - SynchronizerJobPtr syncRenderViewInitializationJob() const; - SynchronizerJobPtr syncFrustumCullingJob() const; - SynchronizerJobPtr syncRenderCommandBuildingJob() const; - SynchronizerJobPtr syncRenderViewCommandBuildersJob() const; - SynchronizerJobPtr setClearDrawBufferIndexJob() const; - SynchronizerJobPtr syncFilterEntityByLayerJob() const; - FilterProximityDistanceJobPtr filterProximityJob() const; - SynchronizerJobPtr syncMaterialGathererJob() const; - - void prepareJobs(); - QVector<Qt3DCore::QAspectJobPtr> buildJobHierachy() const; - - Renderer *renderer() const; - int renderViewIndex() const; - - void setLayerCacheNeedsToBeRebuilt(bool needsToBeRebuilt); - bool layerCacheNeedsToBeRebuilt() const; - void setMaterialGathererCacheNeedsToBeRebuilt(bool needsToBeRebuilt); - bool materialGathererCacheNeedsToBeRebuilt() const; - - static int optimalJobCount(); - static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset); - -private: - Render::FrameGraphNode *m_leafNode; - const int m_renderViewIndex; - Renderer *m_renderer; - bool m_layerCacheNeedsToBeRebuilt; - bool m_materialGathererCacheNeedsToBeRebuilt; - - RenderViewInitializerJobPtr m_renderViewJob; - FilterLayerEntityJobPtr m_filterEntityByLayerJob; - LightGathererPtr m_lightGathererJob; - RenderableEntityFilterPtr m_renderableEntityFilterJob; - ComputableEntityFilterPtr m_computableEntityFilterJob; - FrustumCullingJobPtr m_frustumCullingJob; - QVector<RenderViewBuilderJobPtr> m_renderViewBuilderJobs; - QVector<MaterialParameterGathererJobPtr> m_materialGathererJobs; - - SynchronizerJobPtr m_syncRenderViewInitializationJob; - SynchronizerJobPtr m_syncFrustumCullingJob; - SynchronizerJobPtr m_syncRenderCommandBuildingJob; - SynchronizerJobPtr m_syncRenderViewCommandBuildersJob; - SynchronizerJobPtr m_setClearDrawBufferIndexJob; - SynchronizerJobPtr m_syncFilterEntityByLayerJob; - SynchronizerJobPtr m_syncMaterialGathererJob; - FilterProximityDistanceJobPtr m_filterProximityJob; - - static const int m_optimalParallelJobCount; -}; - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_RENDERVIEWBUILDER_H diff --git a/src/render/backend/shaderparameterpack.cpp b/src/render/backend/shaderparameterpack.cpp deleted file mode 100644 index f78e45a5e..000000000 --- a/src/render/backend/shaderparameterpack.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "shaderparameterpack_p.h" - -#include <Qt3DRender/private/graphicscontext_p.h> -#include <Qt3DRender/private/texture_p.h> - -#include <Qt3DCore/private/qframeallocator_p.h> - -#include <QOpenGLShaderProgram> -#include <QDebug> -#include <QColor> -#include <QQuaternion> -#include <Qt3DRender/private/renderlogging_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { -namespace Render { - -ShaderParameterPack::~ShaderParameterPack() -{ - m_uniforms.clear(); -} - -void ShaderParameterPack::setUniform(const int glslNameId, const UniformValue &val) -{ - m_uniforms.insert(glslNameId, val); -} - -void ShaderParameterPack::setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId texId) -{ - for (int t=0; t<m_textures.size(); ++t) { - if (m_textures[t].glslNameId != glslNameId || m_textures[t].uniformArrayIndex != uniformArrayIndex) - continue; - - m_textures[t].texId = texId; - return; - } - - m_textures.append(NamedTexture(glslNameId, texId, uniformArrayIndex)); -} - -// Contains Uniform Block Index and QNodeId of the ShaderData (UBO) -void ShaderParameterPack::setUniformBuffer(BlockToUBO blockToUBO) -{ - m_uniformBuffers.append(std::move(blockToUBO)); -} - -void ShaderParameterPack::setShaderStorageBuffer(BlockToSSBO blockToSSBO) -{ - m_shaderStorageBuffers.push_back(std::move(blockToSSBO)); -} - -void ShaderParameterPack::setSubmissionUniform(const ShaderUniform &uniform) -{ - m_submissionUniforms.push_back(uniform); -} - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE diff --git a/src/render/backend/shaderparameterpack_p.h b/src/render/backend/shaderparameterpack_p.h deleted file mode 100644 index 5703bb17b..000000000 --- a/src/render/backend/shaderparameterpack_p.h +++ /dev/null @@ -1,145 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_SHADERPARAMETERPACK_P_H -#define QT3DRENDER_RENDER_SHADERPARAMETERPACK_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <QVariant> -#include <QByteArray> -#include <QVector> -#include <QOpenGLShaderProgram> -#include <Qt3DCore/qnodeid.h> -#include <Qt3DRender/private/renderlogging_p.h> -#include <Qt3DRender/private/shadervariables_p.h> -#include <Qt3DRender/private/uniform_p.h> - -QT_BEGIN_NAMESPACE - -class QOpenGLShaderProgram; - -namespace Qt3DCore { -class QFrameAllocator; -} - -namespace Qt3DRender { -namespace Render { - -class GraphicsContext; - -struct BlockToUBO { - int m_blockIndex; - Qt3DCore::QNodeId m_bufferID; - bool m_needsUpdate; - QHash<QString, QVariant> m_updatedProperties; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, BlockToUBO, Q_MOVABLE_TYPE) - -struct BlockToSSBO { - int m_blockIndex; - Qt3DCore::QNodeId m_bufferID; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, BlockToSSBO, Q_PRIMITIVE_TYPE) - - -typedef QHash<int, UniformValue> PackUniformHash; - -class Q_AUTOTEST_EXPORT ShaderParameterPack -{ -public: - ~ShaderParameterPack(); - - void setUniform(const int glslNameId, const UniformValue &val); - void setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); - void setUniformBuffer(BlockToUBO blockToUBO); - void setShaderStorageBuffer(BlockToSSBO blockToSSBO); - void setSubmissionUniform(const ShaderUniform &uniform); - - inline PackUniformHash &uniforms() { return m_uniforms; } - inline const PackUniformHash &uniforms() const { return m_uniforms; } - UniformValue uniform(const int glslNameId) const { return m_uniforms.value(glslNameId); } - - struct NamedTexture - { - NamedTexture() {} - NamedTexture(const int glslNameId, Qt3DCore::QNodeId texId, int uniformArrayIndex) - : glslNameId(glslNameId) - , texId(texId) - , uniformArrayIndex(uniformArrayIndex) - { } - - int glslNameId; - Qt3DCore::QNodeId texId; - int uniformArrayIndex; - }; - - inline QVector<NamedTexture> textures() const { return m_textures; } - inline QVector<BlockToUBO> uniformBuffers() const { return m_uniformBuffers; } - inline QVector<BlockToSSBO> shaderStorageBuffers() const { return m_shaderStorageBuffers; } - inline QVector<ShaderUniform> submissionUniforms() const { return m_submissionUniforms; } -private: - PackUniformHash m_uniforms; - - QVector<NamedTexture> m_textures; - QVector<BlockToUBO> m_uniformBuffers; - QVector<BlockToSSBO> m_shaderStorageBuffers; - QVector<ShaderUniform> m_submissionUniforms; - - friend class RenderView; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderParameterPack::NamedTexture, Q_PRIMITIVE_TYPE) - -} // namespace Render -} // namespace Qt3DRender - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(Qt3DRender::Render::ShaderParameterPack) - -#endif // QT3DRENDER_RENDER_SHADERPARAMETERPACK_P_H diff --git a/src/render/backend/shadervariables_p.h b/src/render/backend/shadervariables_p.h deleted file mode 100644 index e0fa07dff..000000000 --- a/src/render/backend/shadervariables_p.h +++ /dev/null @@ -1,152 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB). -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the Qt3D module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QT3DRENDER_RENDER_SHADERVARIABLES_P_H -#define QT3DRENDER_RENDER_SHADERVARIABLES_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of other Qt classes. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include <Qt3DRender/qt3drender_global.h> -#include <QOpenGLContext> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -struct ShaderAttribute -{ - ShaderAttribute() - : m_nameId(-1) - , m_type(0) - , m_size(0) - , m_location(-1) - {} - - QString m_name; - int m_nameId; - GLenum m_type; - int m_size; - int m_location; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderAttribute, Q_MOVABLE_TYPE) - -struct ShaderUniform -{ - ShaderUniform() - : m_nameId(-1) - , m_type(GL_NONE) - , m_size(0) - , m_offset(-1) - , m_location(-1) - , m_blockIndex(-1) - , m_arrayStride(-1) - , m_matrixStride(-1) - , m_rawByteSize(0) - {} - - QString m_name; - int m_nameId; - GLenum m_type; - int m_size; - int m_offset; // -1 default, >= 0 if uniform defined in uniform block - int m_location; // -1 if uniform defined in a uniform block - int m_blockIndex; // -1 is the default, >= 0 if uniform defined in uniform block - int m_arrayStride; // -1 is the default, >= 0 if uniform defined in uniform block and if it's an array - int m_matrixStride; // -1 is the default, >= 0 uniform defined in uniform block and is a matrix - uint m_rawByteSize; // contains byte size (size / type / strides) - // size, offset and strides are in bytes -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderUniform, Q_MOVABLE_TYPE) - -struct ShaderUniformBlock -{ - ShaderUniformBlock() - : m_nameId(-1) - , m_index(-1) - , m_binding(-1) - , m_activeUniformsCount(0) - , m_size(0) - {} - - QString m_name; - int m_nameId; - int m_index; - int m_binding; - int m_activeUniformsCount; - int m_size; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderUniformBlock, Q_MOVABLE_TYPE) - -struct ShaderStorageBlock -{ - ShaderStorageBlock() - : m_nameId(-1) - , m_index(-1) - , m_binding(-1) - , m_size(0) - , m_activeVariablesCount(0) - {} - - QString m_name; - int m_nameId; - int m_index; - int m_binding; - int m_size; - int m_activeVariablesCount; -}; -QT3D_DECLARE_TYPEINFO_2(Qt3DRender, Render, ShaderStorageBlock, Q_MOVABLE_TYPE) - -} // namespace Render - -} // namespace Qt3DRender - -QT_END_NAMESPACE - -#endif // QT3DRENDER_RENDER_SHADERVARIABLES_P_H |