mirror of https://github.com/qt/qt3d.git
Perform Shader loading within frame
- CommandThread has been improved to not use an exec loop and properly instantiate its own GL context + GraphicsContext that is bound to an offscreen surface - The dirtyShaderGathering job has been renamed and now performs the loading of shaders and their introspection. It is also run before the materiaparameter gathering, so that these jobs and the following can assume a shader is ready Change-Id: I6d99b3a104bd96530dc45f4b05d3aaac09d2d077 Reviewed-by: Mike Krus <mike.krus@kdab.com> Reviewed-by: Svenn-Arne Dragly <svenn-arne.dragly@qt.io> Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
This commit is contained in:
parent
c1b495f70c
commit
00b7e4b76a
|
|
@ -38,7 +38,13 @@
|
|||
****************************************************************************/
|
||||
|
||||
#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
|
||||
|
||||
|
|
@ -51,6 +57,13 @@ CommandThread::CommandThread(Renderer *renderer)
|
|||
, 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)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -58,8 +71,13 @@ CommandThread::~CommandThread()
|
|||
{
|
||||
}
|
||||
|
||||
void CommandThread::setShaderCache(ShaderCache *shaderCache)
|
||||
{
|
||||
m_shaderCache = shaderCache;
|
||||
}
|
||||
|
||||
// Called by RenderThread or MainThread (Scene3d)
|
||||
void CommandThread::initialize(QOpenGLContext *mainContext)
|
||||
void CommandThread::initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper)
|
||||
{
|
||||
// Start the thread
|
||||
start();
|
||||
|
|
@ -68,36 +86,58 @@ void CommandThread::initialize(QOpenGLContext *mainContext)
|
|||
m_waitForStartSemaphore.acquire();
|
||||
|
||||
m_mainContext = mainContext;
|
||||
Q_ASSERT(m_mainContext);
|
||||
m_offsreenSurfaceHelper = offsreenSurfaceHelper;
|
||||
Q_ASSERT(m_mainContext && offsreenSurfaceHelper);
|
||||
m_running.fetchAndStoreOrdered(1);
|
||||
|
||||
// Allow thread to proceed
|
||||
m_initializedSemaphore.release();
|
||||
}
|
||||
|
||||
// Called by RenderThread of MainThread (Scene3D)
|
||||
// Called by RenderThread or MainThread (Scene3D)
|
||||
void CommandThread::shutdown()
|
||||
{
|
||||
// Tell thread to exit event loop
|
||||
QThread::quit();
|
||||
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.release(m_waitForStartSemaphore.available());
|
||||
m_initializedSemaphore.release(m_initializedSemaphore.available());
|
||||
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(Command *command)
|
||||
void CommandThread::executeCommand(GLCommand *command)
|
||||
{
|
||||
if (!isRunning())
|
||||
return;
|
||||
QMetaObject::invokeMethod(this,
|
||||
"executeCommandInternal",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_ARG(Command*, command));
|
||||
|
||||
// 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()
|
||||
|
|
@ -108,18 +148,44 @@ void CommandThread::run()
|
|||
// 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();
|
||||
|
||||
// Launch exec loop
|
||||
QThread::exec();
|
||||
}
|
||||
// Initialize GraphicsContext
|
||||
m_graphicsContext.reset(new GraphicsContext());
|
||||
m_graphicsContext->setShaderCache(m_shaderCache);
|
||||
m_graphicsContext->setOpenGLContext(m_localContext.data());
|
||||
|
||||
// Executed in the Command Thread
|
||||
void CommandThread::executeCommandInternal(Command *command)
|
||||
{
|
||||
command->execute(m_renderer, 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
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@
|
|||
|
||||
#include <QtCore/QThread>
|
||||
#include <QtCore/QSemaphore>
|
||||
#include <QtCore/QMutex>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -63,12 +64,10 @@ namespace Qt3DRender {
|
|||
namespace Render {
|
||||
|
||||
class Renderer;
|
||||
|
||||
class Command
|
||||
{
|
||||
public:
|
||||
virtual void execute(Renderer *renderer, QOpenGLContext *localContext) = 0;
|
||||
};
|
||||
class GLCommand;
|
||||
class OffscreenSurfaceHelper;
|
||||
class GraphicsContext;
|
||||
class ShaderCache;
|
||||
|
||||
class CommandThread : public QThread
|
||||
{
|
||||
|
|
@ -79,21 +78,32 @@ public:
|
|||
|
||||
Render::Renderer* renderer() const { return m_renderer; }
|
||||
|
||||
void initialize(QOpenGLContext *mainContext);
|
||||
void setShaderCache(ShaderCache *shaderCache);
|
||||
ShaderCache *shaderCache() const { return m_shaderCache; }
|
||||
|
||||
void initialize(QOpenGLContext *mainContext, OffscreenSurfaceHelper *offsreenSurfaceHelper);
|
||||
void shutdown();
|
||||
|
||||
void executeCommand(Command *command);
|
||||
void executeCommand(GLCommand *command);
|
||||
|
||||
private:
|
||||
void run() override;
|
||||
Q_INVOKABLE void executeCommandInternal(Command *command);
|
||||
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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
/****************************************************************************
|
||||
**
|
||||
** 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
|
||||
|
|
@ -45,7 +45,8 @@ HEADERS += \
|
|||
$$PWD/visitorutils_p.h \
|
||||
$$PWD/segmentsvisitor_p.h \
|
||||
$$PWD/pointsvisitor_p.h \
|
||||
$$PWD/renderercache_p.h
|
||||
$$PWD/renderercache_p.h \
|
||||
$$PWD/glcommands_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/renderthread.cpp \
|
||||
|
|
@ -82,7 +83,8 @@ SOURCES += \
|
|||
$$PWD/resourceaccessor.cpp \
|
||||
$$PWD/segmentsvisitor.cpp \
|
||||
$$PWD/commandthread.cpp \
|
||||
$$PWD/pointsvisitor.cpp
|
||||
$$PWD/pointsvisitor.cpp \
|
||||
$$PWD/glcommands.cpp
|
||||
|
||||
include($$QT3D_BUILD_ROOT/src/core/qt3dcore-config.pri)
|
||||
QT_FOR_CONFIG += 3dcore-private
|
||||
|
|
|
|||
|
|
@ -90,6 +90,7 @@
|
|||
#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>
|
||||
|
|
@ -188,7 +189,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
|
|||
, 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_shaderGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyShaders(); }, JobTypes::DirtyShaderGathering))
|
||||
, 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)
|
||||
|
|
@ -223,7 +224,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
|
|||
m_pickBoundingVolumeJob->addDependency(m_updateMeshTriangleListJob);
|
||||
m_rayCastingJob->addDependency(m_updateMeshTriangleListJob);
|
||||
|
||||
m_shaderGathererJob->addDependency(m_filterCompatibleTechniqueJob);
|
||||
m_introspectShaderJob->addDependency(m_filterCompatibleTechniqueJob);
|
||||
|
||||
m_filterCompatibleTechniqueJob->setRenderer(this);
|
||||
|
||||
|
|
@ -321,9 +322,12 @@ QOpenGLContext *Renderer::shareContext() const
|
|||
: nullptr);
|
||||
}
|
||||
|
||||
// Executed in the command thread
|
||||
void Renderer::loadShader(Shader *shader) const
|
||||
{
|
||||
Q_UNUSED(shader);
|
||||
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload);
|
||||
LoadShaderCommand cmd(shader);
|
||||
m_commandThread->executeCommand(&cmd);
|
||||
}
|
||||
|
||||
void Renderer::setOpenGLContext(QOpenGLContext *context)
|
||||
|
|
@ -380,6 +384,7 @@ void Renderer::initialize()
|
|||
|
||||
// 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)
|
||||
|
|
@ -392,6 +397,13 @@ void Renderer::initialize()
|
|||
// (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
|
||||
|
|
@ -1037,7 +1049,7 @@ void Renderer::lookForDirtyTextures()
|
|||
}
|
||||
|
||||
// Executed in a job
|
||||
void Renderer::lookForDirtyShaders()
|
||||
void Renderer::reloadDirtyShaders()
|
||||
{
|
||||
Q_ASSERT(isRunning());
|
||||
const QVector<HTechnique> activeTechniques = m_nodesManager->techniqueManager()->activeHandles();
|
||||
|
|
@ -1102,8 +1114,9 @@ void Renderer::lookForDirtyShaders()
|
|||
|
||||
if (Q_UNLIKELY(shader->hasPendingNotifications()))
|
||||
shader->submitPendingNotifications();
|
||||
// If the shader hasn't be loaded, load it
|
||||
if (shader != nullptr && !shader->isLoaded())
|
||||
m_dirtyShaders.push_back(shaderHandle);
|
||||
loadShader(shader);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1127,17 +1140,6 @@ void Renderer::updateGLResources()
|
|||
}
|
||||
}
|
||||
|
||||
{
|
||||
Profiling::GLTimeRecorder recorder(Profiling::ShaderUpload);
|
||||
const QVector<HShader> dirtyShaderHandles = std::move(m_dirtyShaders);
|
||||
ShaderManager *shaderManager = m_nodesManager->shaderManager();
|
||||
for (const HShader &handle: dirtyShaderHandles) {
|
||||
Shader *shader = shaderManager->data(handle);
|
||||
// Compile shader
|
||||
m_submissionContext->loadShader(shader, shaderManager);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Profiling::GLTimeRecorder recorder(Profiling::TextureUpload);
|
||||
const QVector<HTexture> activeTextureHandles = std::move(m_dirtyTextures);
|
||||
|
|
@ -1624,7 +1626,7 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
|
|||
if (dirtyBitsForFrame & AbstractRenderer::TechniquesDirty )
|
||||
renderBinJobs.push_back(m_filterCompatibleTechniqueJob);
|
||||
if (dirtyBitsForFrame & AbstractRenderer::ShadersDirty)
|
||||
renderBinJobs.push_back(m_shaderGathererJob);
|
||||
renderBinJobs.push_back(m_introspectShaderJob);
|
||||
} else {
|
||||
notCleared |= AbstractRenderer::TechniquesDirty;
|
||||
notCleared |= AbstractRenderer::ShadersDirty;
|
||||
|
|
|
|||
|
|
@ -148,6 +148,7 @@ 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
|
||||
{
|
||||
|
|
@ -211,7 +212,7 @@ public:
|
|||
inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
|
||||
inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; }
|
||||
inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
|
||||
inline Qt3DCore::QAspectJobPtr shaderGathererJob() const { return m_shaderGathererJob; }
|
||||
inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
|
||||
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
|
||||
inline Qt3DCore::QAspectJobPtr textureGathererJob() const { return m_textureGathererJob; }
|
||||
|
||||
|
|
@ -365,7 +366,7 @@ private:
|
|||
GenericLambdaJobPtr<std::function<void ()>> m_bufferGathererJob;
|
||||
GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
|
||||
GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
|
||||
GenericLambdaJobPtr<std::function<void ()>> m_shaderGathererJob;
|
||||
IntrospectShadersJobPtr m_introspectShaderJob;
|
||||
|
||||
SynchronizerJobPtr m_syncTextureLoadingJob;
|
||||
|
||||
|
|
@ -373,14 +374,13 @@ private:
|
|||
void lookForDirtyBuffers();
|
||||
void lookForDownloadableBuffers();
|
||||
void lookForDirtyTextures();
|
||||
void lookForDirtyShaders();
|
||||
void reloadDirtyShaders();
|
||||
|
||||
QMutex m_abandonedVaosMutex;
|
||||
QVector<HVao> m_abandonedVaos;
|
||||
|
||||
QVector<HBuffer> m_dirtyBuffers;
|
||||
QVector<HBuffer> m_downloadableBuffers;
|
||||
QVector<HShader> m_dirtyShaders;
|
||||
QVector<HTexture> m_dirtyTextures;
|
||||
|
||||
bool m_ownedContext;
|
||||
|
|
|
|||
|
|
@ -934,8 +934,8 @@ void RenderView::setShaderAndUniforms(RenderCommand *command,
|
|||
if (rPass != nullptr) {
|
||||
// Index Shader by Shader UUID
|
||||
command->m_shader = m_manager->lookupHandle<Shader, ShaderManager, HShader>(rPass->shaderProgram());
|
||||
Shader *shader = nullptr;
|
||||
if ((shader = m_manager->data<Shader, ShaderManager>(command->m_shader)) != nullptr) {
|
||||
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
|
||||
|
|
|
|||
|
|
@ -559,7 +559,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
|
|||
|
||||
// Ensure the RenderThread won't be able to process dirtyResources
|
||||
// before they have been completely gathered
|
||||
m_syncRenderCommandBuildingJob->addDependency(m_renderer->shaderGathererJob());
|
||||
m_syncRenderCommandBuildingJob->addDependency(m_renderer->introspectShadersJob());
|
||||
m_syncRenderCommandBuildingJob->addDependency(m_renderer->bufferGathererJob());
|
||||
m_syncRenderCommandBuildingJob->addDependency(m_renderer->textureGathererJob());
|
||||
|
||||
|
|
@ -598,6 +598,7 @@ QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const
|
|||
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);
|
||||
|
|
|
|||
|
|
@ -213,8 +213,10 @@ void GraphicsContext::doneCurrent()
|
|||
{
|
||||
Q_ASSERT(m_gl);
|
||||
m_gl->doneCurrent();
|
||||
m_glHelper = nullptr;
|
||||
}
|
||||
|
||||
// Called by GL Command Thread
|
||||
QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode)
|
||||
{
|
||||
QScopedPointer<QOpenGLShaderProgram> shaderProgram(new QOpenGLShaderProgram);
|
||||
|
|
@ -249,17 +251,21 @@ QOpenGLShaderProgram *GraphicsContext::createShaderProgram(Shader *shaderNode)
|
|||
return shaderProgram.take();
|
||||
}
|
||||
|
||||
// Called by GL Command Thread (can't use global glHelpers)
|
||||
// That assumes that the shaderProgram in Shader stays the same
|
||||
void GraphicsContext::introspectShaderInterface(Shader *shader, QOpenGLShaderProgram *shaderProgram)
|
||||
{
|
||||
shader->initializeUniforms(m_glHelper->programUniformsAndLocations(shaderProgram->programId()));
|
||||
shader->initializeAttributes(m_glHelper->programAttributesAndLocations(shaderProgram->programId()));
|
||||
GraphicsHelperInterface *glHelper = resolveHighestOpenGLFunctions();
|
||||
shader->initializeUniforms(glHelper->programUniformsAndLocations(shaderProgram->programId()));
|
||||
shader->initializeAttributes(glHelper->programAttributesAndLocations(shaderProgram->programId()));
|
||||
if (m_glHelper->supportsFeature(GraphicsHelperInterface::UniformBufferObject))
|
||||
shader->initializeUniformBlocks(m_glHelper->programUniformBlocks(shaderProgram->programId()));
|
||||
shader->initializeUniformBlocks(glHelper->programUniformBlocks(shaderProgram->programId()));
|
||||
if (m_glHelper->supportsFeature(GraphicsHelperInterface::ShaderStorageObject))
|
||||
shader->initializeShaderStorageBlocks(m_glHelper->programShaderStorageBlocks(shaderProgram->programId()));
|
||||
shader->initializeShaderStorageBlocks(glHelper->programShaderStorageBlocks(shaderProgram->programId()));
|
||||
}
|
||||
|
||||
|
||||
// Called by GL Command Thread
|
||||
void GraphicsContext::loadShader(Shader *shader, ShaderManager *manager)
|
||||
{
|
||||
bool wasPresent = false;
|
||||
|
|
|
|||
|
|
@ -296,7 +296,8 @@ private Q_SLOTS:
|
|||
QVERIFY(renderViewBuilder.syncFrustumCullingJob()->dependencies().contains(testAspect.renderer()->updateShaderDataTransformJob()));
|
||||
|
||||
for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
|
||||
QCOMPARE(materialGatherer->dependencies().size(), 2);
|
||||
QCOMPARE(materialGatherer->dependencies().size(), 3);
|
||||
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
|
||||
QVERIFY(materialGatherer->dependencies().contains(renderViewBuilder.syncRenderViewInitializationJob()));
|
||||
QVERIFY(materialGatherer->dependencies().contains(testAspect.renderer()->filterCompatibleTechniqueJob()));
|
||||
}
|
||||
|
|
@ -314,7 +315,7 @@ private Q_SLOTS:
|
|||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->shaderGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
|
||||
for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
|
||||
|
|
@ -390,7 +391,7 @@ private Q_SLOTS:
|
|||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.lightGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.frustumCullingJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(renderViewBuilder.filterProximityJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->shaderGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->introspectShadersJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->bufferGathererJob()));
|
||||
QVERIFY(renderViewBuilder.syncRenderCommandBuildingJob()->dependencies().contains(testAspect.renderer()->textureGathererJob()));
|
||||
for (const auto materialGatherer : renderViewBuilder.materialGathererJobs()) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue