diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/render/backend/commandthread.cpp | 108 | ||||
-rw-r--r-- | src/render/backend/commandthread_p.h | 28 | ||||
-rw-r--r-- | src/render/backend/glcommands.cpp | 67 | ||||
-rw-r--r-- | src/render/backend/glcommands_p.h | 89 | ||||
-rw-r--r-- | src/render/backend/render-backend.pri | 6 | ||||
-rw-r--r-- | src/render/backend/renderer.cpp | 36 | ||||
-rw-r--r-- | src/render/backend/renderer_p.h | 8 | ||||
-rw-r--r-- | src/render/backend/renderview.cpp | 4 | ||||
-rw-r--r-- | src/render/backend/renderviewbuilder.cpp | 3 | ||||
-rw-r--r-- | src/render/graphicshelpers/graphicscontext.cpp | 14 |
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; |