summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/render/backend/commandthread.cpp108
-rw-r--r--src/render/backend/commandthread_p.h28
-rw-r--r--src/render/backend/glcommands.cpp67
-rw-r--r--src/render/backend/glcommands_p.h89
-rw-r--r--src/render/backend/render-backend.pri6
-rw-r--r--src/render/backend/renderer.cpp36
-rw-r--r--src/render/backend/renderer_p.h8
-rw-r--r--src/render/backend/renderview.cpp4
-rw-r--r--src/render/backend/renderviewbuilder.cpp3
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp14
10 files changed, 303 insertions, 60 deletions
diff --git a/src/render/backend/commandthread.cpp b/src/render/backend/commandthread.cpp
index 9e764f0dd..387fc1113 100644
--- a/src/render/backend/commandthread.cpp
+++ b/src/render/backend/commandthread.cpp
@@ -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);
-
- // Launch exec loop
- QThread::exec();
-}
-
-// Executed in the Command Thread
-void CommandThread::executeCommandInternal(Command *command)
-{
- command->execute(m_renderer, m_localContext.data());
+ 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
diff --git a/src/render/backend/commandthread_p.h b/src/render/backend/commandthread_p.h
index a87d13a2e..0508675c4 100644
--- a/src/render/backend/commandthread_p.h
+++ b/src/render/backend/commandthread_p.h
@@ -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
diff --git a/src/render/backend/glcommands.cpp b/src/render/backend/glcommands.cpp
new file mode 100644
index 000000000..fd7ee9fe8
--- /dev/null
+++ b/src/render/backend/glcommands.cpp
@@ -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
diff --git a/src/render/backend/glcommands_p.h b/src/render/backend/glcommands_p.h
new file mode 100644
index 000000000..5ed360759
--- /dev/null
+++ b/src/render/backend/glcommands_p.h
@@ -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
diff --git a/src/render/backend/render-backend.pri b/src/render/backend/render-backend.pri
index f7f30b5c9..cde9e77b9 100644
--- a/src/render/backend/render-backend.pri
+++ b/src/render/backend/render-backend.pri
@@ -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
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index cdec9af01..2611fb6cc 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -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);
}
}
}
@@ -1128,17 +1141,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);
for (const HTexture &handle: activeTextureHandles) {
@@ -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;
diff --git a/src/render/backend/renderer_p.h b/src/render/backend/renderer_p.h
index d174fa428..b4ad0b0fe 100644
--- a/src/render/backend/renderer_p.h
+++ b/src/render/backend/renderer_p.h
@@ -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;
diff --git a/src/render/backend/renderview.cpp b/src/render/backend/renderview.cpp
index 8a45e1fa9..c29448570 100644
--- a/src/render/backend/renderview.cpp
+++ b/src/render/backend/renderview.cpp
@@ -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
diff --git a/src/render/backend/renderviewbuilder.cpp b/src/render/backend/renderviewbuilder.cpp
index 2fd8e4acf..d08bd6dd4 100644
--- a/src/render/backend/renderviewbuilder.cpp
+++ b/src/render/backend/renderviewbuilder.cpp
@@ -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);
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index ddd7281d1..c2ec3db59 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -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;