diff options
Diffstat (limited to 'src/plugins/renderers/opengl')
25 files changed, 893 insertions, 426 deletions
diff --git a/src/plugins/renderers/opengl/debug/imguirenderer.cpp b/src/plugins/renderers/opengl/debug/imguirenderer.cpp index 8dd9b98fe..0acee945a 100644 --- a/src/plugins/renderers/opengl/debug/imguirenderer.cpp +++ b/src/plugins/renderers/opengl/debug/imguirenderer.cpp @@ -283,13 +283,21 @@ void ImGuiRenderer::renderDebugOverlay(const QVector<RenderView *> &renderViews, QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand", Qt::QueuedConnection, Q_ARG(QString, QLatin1String("render framegraph"))); ImGui::SameLine(); - if (ImGui::Button("FrameGraph Paths##1")) + if (ImGui::Button("Render Views##1")) QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand", Qt::QueuedConnection, Q_ARG(QString, QLatin1String("render framepaths"))); + + ImGui::AlignTextToFramePadding(); + ImGui::Text(" "); + ImGui::SameLine(); + if (ImGui::Button("Filter State##1")) + QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand", + Qt::QueuedConnection, Q_ARG(QString, QLatin1String("render filterstates"))); ImGui::SameLine(); if (ImGui::Button("JobsGraph##1")) QMetaObject::invokeMethod(m_renderer->services()->systemInformation(), "dumpCommand", Qt::QueuedConnection, Q_ARG(QString, QLatin1String("dump jobs"))); + ImGui::End(); if (m_showGLInfoWindow) diff --git a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp index 519f2ae98..d4d3457ab 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp +++ b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext.cpp @@ -1166,7 +1166,7 @@ void SubmissionContext::setUpdatedTexture(const Qt3DCore::QNodeIdVector &updated // It will be easier if the QGraphicContext applies the QUniformPack // than the other way around -bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) +bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack, GLShader *shader) { static const int irradianceId = StringToInt::lookupId(QLatin1String("envLight.irradiance")); static const int specularId = StringToInt::lookupId(QLatin1String("envLight.specular")); @@ -1231,7 +1231,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) } } - QOpenGLShaderProgram *shader = activeShader(); + QOpenGLShaderProgram *glShader = activeShader(); // TO DO: We could cache the binding points somehow and only do the binding when necessary // for SSBO and UBO @@ -1245,7 +1245,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) // This is currently not required as we are introspecting the bindingIndex // value from the shaders and not replacing them, making such a call useless // bindShaderStorageBlock(shader->programId(), b.m_blockIndex, b.m_bindingIndex); - bindShaderStorageBlock(shader->programId(), b.m_blockIndex, b.m_bindingIndex); + bindShaderStorageBlock(glShader->programId(), b.m_blockIndex, b.m_bindingIndex); // Needed to avoid conflict where the buffer would already // be bound as a VertexArray bindGLBuffer(ssbo, GLBuffer::ShaderStorageBuffer); @@ -1260,7 +1260,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) for (const BlockToUBO &b : blockToUBOs) { Buffer *cpuBuffer = m_renderer->nodeManagers()->bufferManager()->lookupResource(b.m_bufferID); GLBuffer *ubo = glBufferForRenderBuffer(cpuBuffer); - bindUniformBlock(shader->programId(), b.m_blockIndex, uboIndex); + bindUniformBlock(glShader->programId(), b.m_blockIndex, uboIndex); // Needed to avoid conflict where the buffer would already // be bound as a VertexArray bindGLBuffer(ubo, GLBuffer::UniformBuffer); @@ -1270,11 +1270,11 @@ bool SubmissionContext::setParameters(ShaderParameterPack ¶meterPack) // Update uniforms in the Default Uniform Block const PackUniformHash values = parameterPack.uniforms(); - const QVector<ShaderUniform> activeUniforms = parameterPack.submissionUniforms(); + const QVector<int> &activeUniformsIndices = parameterPack.submissionUniformIndices(); + const QVector<ShaderUniform> &shaderUniforms = shader->uniforms(); - for (const ShaderUniform &uniform : activeUniforms) { - // We can use [] as we are sure the the uniform wouldn't - // be un activeUniforms if there wasn't a matching value + for (const int shaderUniformIndex : activeUniformsIndices) { + const ShaderUniform &uniform = shaderUniforms[shaderUniformIndex]; const UniformValue &v = values.value(uniform.m_nameId); // skip invalid textures/images diff --git a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext_p.h b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext_p.h index 59b2b78f3..4c895013c 100644 --- a/src/plugins/renderers/opengl/graphicshelpers/submissioncontext_p.h +++ b/src/plugins/renderers/opengl/graphicshelpers/submissioncontext_p.h @@ -137,7 +137,7 @@ public: GLBuffer *glBufferForRenderBuffer(Buffer *buf); // Parameters - bool setParameters(ShaderParameterPack ¶meterPack); + bool setParameters(ShaderParameterPack ¶meterPack, GLShader *shader); // RenderState void setCurrentStateSet(RenderStateSet* ss); diff --git a/src/plugins/renderers/opengl/jobs/materialparametergathererjob.cpp b/src/plugins/renderers/opengl/jobs/materialparametergathererjob.cpp index 1f51ceba3..1dd26b847 100644 --- a/src/plugins/renderers/opengl/jobs/materialparametergathererjob.cpp +++ b/src/plugins/renderers/opengl/jobs/materialparametergathererjob.cpp @@ -59,8 +59,32 @@ const int likelyNumberOfParameters = 24; } // anonymous +class MaterialParameterGathererJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + MaterialParameterGathererJobPrivate(MaterialParameterGathererJob *q) : q_ptr(q) { } + ~MaterialParameterGathererJobPrivate() override = default; + + bool isRequired() const override; + void postFrame(Qt3DCore::QAspectManager *manager) override; + + MaterialParameterGathererJob *q_ptr; + Q_DECLARE_PUBLIC(MaterialParameterGathererJob) +}; + +bool MaterialParameterGathererJobPrivate::isRequired() const +{ + return !q_ptr->m_handles.isEmpty(); +} + +void MaterialParameterGathererJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + Q_UNUSED(manager) + materialParameterGathererCounter = 0; +} + MaterialParameterGathererJob::MaterialParameterGathererJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new MaterialParameterGathererJobPrivate(this)) , m_manager(nullptr) , m_techniqueFilter(nullptr) , m_renderPassFilter(nullptr) diff --git a/src/plugins/renderers/opengl/jobs/materialparametergathererjob_p.h b/src/plugins/renderers/opengl/jobs/materialparametergathererjob_p.h index cd5af8124..8c9997827 100644 --- a/src/plugins/renderers/opengl/jobs/materialparametergathererjob_p.h +++ b/src/plugins/renderers/opengl/jobs/materialparametergathererjob_p.h @@ -71,6 +71,7 @@ namespace OpenGL { class Renderer; // TO be executed for each FrameGraph branch with a given RenderPassFilter/TechniqueFilter +class MaterialParameterGathererJobPrivate; class Q_AUTOTEST_EXPORT MaterialParameterGathererJob : public Qt3DCore::QAspectJob { @@ -96,6 +97,8 @@ private: // Material id to array of RenderPasse with parameters MaterialParameterGathererData m_parameters; QVector<HMaterial> m_handles; + + Q_DECLARE_PRIVATE(MaterialParameterGathererJob) }; typedef QSharedPointer<MaterialParameterGathererJob> MaterialParameterGathererJobPtr; diff --git a/src/plugins/renderers/opengl/jobs/renderviewbuilderjob.cpp b/src/plugins/renderers/opengl/jobs/renderviewbuilderjob.cpp deleted file mode 100644 index 468ab9342..000000000 --- a/src/plugins/renderers/opengl/jobs/renderviewbuilderjob.cpp +++ /dev/null @@ -1,86 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 Paul Lemire -** 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 "renderviewcommandupdaterjob_p.h" -#include <Qt3DRender/private/job_common_p.h> -#include <renderer_p.h> -#include <renderview_p.h> - -QT_BEGIN_NAMESPACE - -namespace Qt3DRender { - -namespace Render { - -namespace OpenGL { - -namespace { -int renderViewInstanceCounter = 0; -} // anonymous - -RenderViewCommandUpdaterJob::RenderViewCommandUpdaterJob() - : Qt3DCore::QAspectJob() - , m_offset(0) - , m_count(0) - , m_renderView(nullptr) - , m_renderer(nullptr) - , m_renderables(nullptr) -{ - SET_JOB_RUN_STAT_TYPE(this, JobTypes::RenderCommandUpdater, renderViewInstanceCounter++); -} - -void RenderViewCommandUpdaterJob::run() -{ - // Build RenderCommand should perform the culling as we have no way to determine - // if a child has a mesh in the view frustum while its parent isn't contained in it. - if (!m_renderView->noDraw()) { - if (m_count == 0) - return; - // Update Render Commands (Uniform Change, Depth Change) - m_renderView->updateRenderCommand(m_renderables, m_offset, m_count); - } -} - -} // OpenGL - -} // Render - -} // Qt3DRender - -QT_END_NAMESPACE diff --git a/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp b/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp index d8a33b693..d5e17e0bf 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp +++ b/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob.cpp @@ -53,8 +53,32 @@ namespace { int renderViewInstanceCounter = 0; } // anonymous +class RenderViewCommandBuilderJobPrivate : public Qt3DCore::QAspectJobPrivate +{ +public: + RenderViewCommandBuilderJobPrivate(RenderViewCommandBuilderJob *q) : q_ptr(q) { } + ~RenderViewCommandBuilderJobPrivate() override = default; + + bool isRequired() const override; + void postFrame(Qt3DCore::QAspectManager *manager) override; + + RenderViewCommandBuilderJob *q_ptr; + Q_DECLARE_PUBLIC(RenderViewCommandBuilderJob) +}; + +bool RenderViewCommandBuilderJobPrivate::isRequired() const +{ + return q_ptr->m_renderView && !q_ptr->m_renderView->noDraw() && q_ptr->m_count > 0; +} + +void RenderViewCommandBuilderJobPrivate::postFrame(Qt3DCore::QAspectManager *manager) +{ + Q_UNUSED(manager) + renderViewInstanceCounter = 0; +} + RenderViewCommandBuilderJob::RenderViewCommandBuilderJob() - : Qt3DCore::QAspectJob() + : Qt3DCore::QAspectJob(*new RenderViewCommandBuilderJobPrivate(this)) , m_offset(0) , m_count(0) , m_renderView(nullptr) @@ -64,18 +88,14 @@ RenderViewCommandBuilderJob::RenderViewCommandBuilderJob() void RenderViewCommandBuilderJob::run() { - if (!m_renderView->noDraw()) { - if (m_count == 0) - return; - - const bool isDraw = !m_renderView->isCompute(); - if (isDraw) - m_commandData = m_renderView->buildDrawRenderCommands(m_entities, m_offset, m_count); - else - m_commandData = m_renderView->buildComputeRenderCommands(m_entities, m_offset, m_count); - } + const bool isDraw = !m_renderView->isCompute(); + if (isDraw) + m_commandData = m_renderView->buildDrawRenderCommands(m_entities, m_offset, m_count); + else + m_commandData = m_renderView->buildComputeRenderCommands(m_entities, m_offset, m_count); } + } // OpenGL } // Render diff --git a/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h b/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h index e9f8bb10a..52c055285 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h +++ b/src/plugins/renderers/opengl/jobs/renderviewcommandbuilderjob_p.h @@ -63,6 +63,8 @@ namespace Render { namespace OpenGL { +class RenderViewCommandBuilderJobPrivate; + class Q_AUTOTEST_EXPORT RenderViewCommandBuilderJob : public Qt3DCore::QAspectJob { public: @@ -85,6 +87,8 @@ private: RenderView *m_renderView; QVector<Entity *> m_entities; EntityRenderCommandData m_commandData; + + Q_DECLARE_PRIVATE(RenderViewCommandBuilderJob) }; typedef QSharedPointer<RenderViewCommandBuilderJob> RenderViewCommandBuilderJobPtr; diff --git a/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp b/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp index ed0854ecf..9bbdf50fd 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp +++ b/src/plugins/renderers/opengl/jobs/renderviewcommandupdaterjob.cpp @@ -60,17 +60,16 @@ public: RenderViewCommandUpdaterJobPrivate(RenderViewCommandUpdaterJob *q) : q_ptr(q) { } ~RenderViewCommandUpdaterJobPrivate() override = default; - bool isRequired() override; + bool isRequired() const override; void postFrame(Qt3DCore::QAspectManager *manager) override; RenderViewCommandUpdaterJob *q_ptr; Q_DECLARE_PUBLIC(RenderViewCommandUpdaterJob) }; -bool RenderViewCommandUpdaterJobPrivate::isRequired() +bool RenderViewCommandUpdaterJobPrivate::isRequired() const { - Q_Q(RenderViewCommandUpdaterJob); - + Q_Q(const RenderViewCommandUpdaterJob); return q->m_renderView && !q->m_renderView->noDraw() && q->m_count > 0; } diff --git a/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp b/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp index d4835054b..8774ac368 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp +++ b/src/plugins/renderers/opengl/jobs/renderviewjobutils.cpp @@ -473,7 +473,10 @@ UniformBlockValueBuilder::~UniformBlockValueBuilder() { } -void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData *currentShaderData, const QString &blockName, const QString &qmlPropertyName, const QVariant &value) +void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData, + const QString &blockName, + const QString &qmlPropertyName, + const QVariant &value) { // In the end, values are either scalar or a scalar array // Composed elements (structs, structs array) are simplified into simple scalars @@ -534,7 +537,9 @@ void UniformBlockValueBuilder::buildActiveUniformNameValueMapHelper(ShaderData * } } -void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName) +void UniformBlockValueBuilder::buildActiveUniformNameValueMapStructHelper(const ShaderData *rShaderData, + const QString &blockName, + const QString &qmlPropertyName) { const QHash<QString, ShaderData::PropertyValue> &properties = rShaderData->properties(); auto it = properties.begin(); diff --git a/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h b/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h index 7b5ba2bfd..bc5bfd8aa 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h +++ b/src/plugins/renderers/opengl/jobs/renderviewjobutils_p.h @@ -162,11 +162,11 @@ struct Q_AUTOTEST_EXPORT UniformBlockValueBuilder QT3D_ALIGNED_MALLOC_AND_FREE() - void buildActiveUniformNameValueMapHelper(ShaderData *currentShaderData, + void buildActiveUniformNameValueMapHelper(const ShaderData *currentShaderData, const QString &blockName, const QString &qmlPropertyName, const QVariant &value); - void buildActiveUniformNameValueMapStructHelper(ShaderData *rShaderData, + void buildActiveUniformNameValueMapStructHelper(const ShaderData *rShaderData, const QString &blockName, const QString &qmlPropertyName = QString()); diff --git a/src/plugins/renderers/opengl/opengl.pro b/src/plugins/renderers/opengl/opengl.pro index ebd4ff5d1..f098513e8 100644 --- a/src/plugins/renderers/opengl/opengl.pro +++ b/src/plugins/renderers/opengl/opengl.pro @@ -1,5 +1,8 @@ TARGET = openglrenderer +# We use QT_AUTOTEST_EXPORT to test the plug-ins, which needs QT_BUILDING_QT +DEFINES += QT_BUILDING_QT + include(opengl.pri) SOURCES += \ diff --git a/src/plugins/renderers/opengl/renderer/gllights.cpp b/src/plugins/renderers/opengl/renderer/gllights.cpp new file mode 100644 index 000000000..c87fd766b --- /dev/null +++ b/src/plugins/renderers/opengl/renderer/gllights.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** Copyright (C) 2020 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 <Qt3DRender/private/stringtoint_p.h> +#include "gllights_p.h" + +#define LIGHT_POSITION_NAME QLatin1String(".position") +#define LIGHT_TYPE_NAME QLatin1String(".type") +#define LIGHT_COLOR_NAME QLatin1String(".color") +#define LIGHT_INTENSITY_NAME QLatin1String(".intensity") +#define LIGHT_DIRECTION_NAME QLatin1String(".direction") +#define LIGHT_LINEAR_ATTENUATION_NAME QLatin1String(".linearAttenuation") +#define LIGHT_QUADRATIC_ATTENUATION_NAME QLatin1String(".quadraticAttenuation") +#define LIGHT_CONSTANT_ATTENUATION_NAME QLatin1String(".constantAttenuation") +#define LIGHT_CUT_OFF_ANGLE_NAME QLatin1String(".cutOffAngle") + +#define DECLARE_LIGHT_STRUCT_NAME(idx)\ + QLatin1String("lights[") + QLatin1Char(char('0' + idx)) + QLatin1Char(']') + +#define DECLARE_LIGHT_POSITION_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_POSITION_NAME) + +#define DECLARE_LIGHT_TYPE_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_TYPE_NAME) + +#define DECLARE_LIGHT_COLOR_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_COLOR_NAME) + +#define DECLARE_LIGHT_INTENSITY_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_INTENSITY_NAME) + +#define DECLARE_LIGHT_DIRECTION_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_DIRECTION_NAME) + +#define DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_LINEAR_ATTENUATION_NAME) + +#define DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_QUADRATIC_ATTENUATION_NAME) + +#define DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_CONSTANT_ATTENUATION_NAME) + +#define DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_NAMES[idx] + LIGHT_CUT_OFF_ANGLE_NAME) + +#define DECLARE_LIGHT_STRUCT_UNROLL_NAME(idx)\ + QLatin1String("light_") + QLatin1Char(char('0' + idx)) + +#define DECLARE_LIGHT_POSITION_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_POSITION_NAME) + +#define DECLARE_LIGHT_TYPE_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_TYPE_NAME) + +#define DECLARE_LIGHT_COLOR_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_COLOR_NAME) + +#define DECLARE_LIGHT_INTENSITY_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_INTENSITY_NAME) + +#define DECLARE_LIGHT_DIRECTION_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_DIRECTION_NAME) + +#define DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_LINEAR_ATTENUATION_NAME) + +#define DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_QUADRATIC_ATTENUATION_NAME) + +#define DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_CONSTANT_ATTENUATION_NAME) + +#define DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(idx)\ + StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[idx] + LIGHT_CUT_OFF_ANGLE_NAME) + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { +namespace Render { +namespace OpenGL { + +int GLLights::LIGHT_COUNT_NAME_ID = StringToInt::lookupId(QLatin1String("lightCount")); + +QString GLLights::LIGHT_STRUCT_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_STRUCT_NAME(0), + DECLARE_LIGHT_STRUCT_NAME(1), + DECLARE_LIGHT_STRUCT_NAME(2), + DECLARE_LIGHT_STRUCT_NAME(3), + DECLARE_LIGHT_STRUCT_NAME(4), + DECLARE_LIGHT_STRUCT_NAME(5), + DECLARE_LIGHT_STRUCT_NAME(6), + DECLARE_LIGHT_STRUCT_NAME(7) +}; + +int GLLights::LIGHT_POSITION_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_POSITION_NAME(0), + DECLARE_LIGHT_POSITION_NAME(1), + DECLARE_LIGHT_POSITION_NAME(2), + DECLARE_LIGHT_POSITION_NAME(3), + DECLARE_LIGHT_POSITION_NAME(4), + DECLARE_LIGHT_POSITION_NAME(5), + DECLARE_LIGHT_POSITION_NAME(6), + DECLARE_LIGHT_POSITION_NAME(7) +}; + +int GLLights::LIGHT_TYPE_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_TYPE_NAME(0), + DECLARE_LIGHT_TYPE_NAME(1), + DECLARE_LIGHT_TYPE_NAME(2), + DECLARE_LIGHT_TYPE_NAME(3), + DECLARE_LIGHT_TYPE_NAME(4), + DECLARE_LIGHT_TYPE_NAME(5), + DECLARE_LIGHT_TYPE_NAME(6), + DECLARE_LIGHT_TYPE_NAME(7) +}; + +int GLLights::LIGHT_COLOR_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_COLOR_NAME(0), + DECLARE_LIGHT_COLOR_NAME(1), + DECLARE_LIGHT_COLOR_NAME(2), + DECLARE_LIGHT_COLOR_NAME(3), + DECLARE_LIGHT_COLOR_NAME(4), + DECLARE_LIGHT_COLOR_NAME(5), + DECLARE_LIGHT_COLOR_NAME(6), + DECLARE_LIGHT_COLOR_NAME(7) +}; + +int GLLights::LIGHT_INTENSITY_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_INTENSITY_NAME(0), + DECLARE_LIGHT_INTENSITY_NAME(1), + DECLARE_LIGHT_INTENSITY_NAME(2), + DECLARE_LIGHT_INTENSITY_NAME(3), + DECLARE_LIGHT_INTENSITY_NAME(4), + DECLARE_LIGHT_INTENSITY_NAME(5), + DECLARE_LIGHT_INTENSITY_NAME(6), + DECLARE_LIGHT_INTENSITY_NAME(7) +}; + +int GLLights::LIGHT_DIRECTION_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_DIRECTION_NAME(0), + DECLARE_LIGHT_DIRECTION_NAME(1), + DECLARE_LIGHT_DIRECTION_NAME(2), + DECLARE_LIGHT_DIRECTION_NAME(3), + DECLARE_LIGHT_DIRECTION_NAME(4), + DECLARE_LIGHT_DIRECTION_NAME(5), + DECLARE_LIGHT_DIRECTION_NAME(6), + DECLARE_LIGHT_DIRECTION_NAME(7) +}; + +int GLLights::LIGHT_LINEAR_ATTENUATION_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(0), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(1), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(2), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(3), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(4), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(5), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(6), + DECLARE_LIGHT_LINEAR_ATTENUATION_NAME(7) +}; + +int GLLights::LIGHT_QUADRATIC_ATTENUATION_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(0), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(1), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(2), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(3), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(4), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(5), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(6), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_NAME(7) +}; + +int GLLights::LIGHT_CONSTANT_ATTENUATION_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(0), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(1), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(2), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(3), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(4), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(5), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(6), + DECLARE_LIGHT_CONSTANT_ATTENUATION_NAME(7) +}; + +int GLLights::LIGHT_CUT_OFF_ANGLE_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(0), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(1), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(2), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(3), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(4), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(5), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(6), + DECLARE_LIGHT_CUT_OFF_ANGLE_NAME(7) +}; + +QString GLLights::LIGHT_STRUCT_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_STRUCT_UNROLL_NAME(0), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(1), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(2), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(3), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(4), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(5), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(6), + DECLARE_LIGHT_STRUCT_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_POSITION_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_POSITION_UNROLL_NAME(0), + DECLARE_LIGHT_POSITION_UNROLL_NAME(1), + DECLARE_LIGHT_POSITION_UNROLL_NAME(2), + DECLARE_LIGHT_POSITION_UNROLL_NAME(3), + DECLARE_LIGHT_POSITION_UNROLL_NAME(4), + DECLARE_LIGHT_POSITION_UNROLL_NAME(5), + DECLARE_LIGHT_POSITION_UNROLL_NAME(6), + DECLARE_LIGHT_POSITION_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_TYPE_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_TYPE_UNROLL_NAME(0), + DECLARE_LIGHT_TYPE_UNROLL_NAME(1), + DECLARE_LIGHT_TYPE_UNROLL_NAME(2), + DECLARE_LIGHT_TYPE_UNROLL_NAME(3), + DECLARE_LIGHT_TYPE_UNROLL_NAME(4), + DECLARE_LIGHT_TYPE_UNROLL_NAME(5), + DECLARE_LIGHT_TYPE_UNROLL_NAME(6), + DECLARE_LIGHT_TYPE_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_COLOR_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_COLOR_UNROLL_NAME(0), + DECLARE_LIGHT_COLOR_UNROLL_NAME(1), + DECLARE_LIGHT_COLOR_UNROLL_NAME(2), + DECLARE_LIGHT_COLOR_UNROLL_NAME(3), + DECLARE_LIGHT_COLOR_UNROLL_NAME(4), + DECLARE_LIGHT_COLOR_UNROLL_NAME(5), + DECLARE_LIGHT_COLOR_UNROLL_NAME(6), + DECLARE_LIGHT_COLOR_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_INTENSITY_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(0), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(1), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(2), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(3), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(4), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(5), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(6), + DECLARE_LIGHT_INTENSITY_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_DIRECTION_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(0), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(1), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(2), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(3), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(4), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(5), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(6), + DECLARE_LIGHT_DIRECTION_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_LINEAR_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(0), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(1), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(2), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(3), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(4), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(5), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(6), + DECLARE_LIGHT_LINEAR_ATTENUATION_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(0), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(1), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(2), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(3), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(4), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(5), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(6), + DECLARE_LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_CONSTANT_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(0), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(1), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(2), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(3), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(4), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(5), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(6), + DECLARE_LIGHT_CONSTANT_ATTENUATION_UNROLL_NAME(7) +}; + +int GLLights::LIGHT_CUT_OFF_ANGLE_UNROLL_NAMES[MAX_LIGHTS] = { + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(0), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(1), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(2), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(3), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(4), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(5), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(6), + DECLARE_LIGHT_CUT_OFF_ANGLE_UNROLL_NAME(7) +}; + +} // namespace OpenGL +} // namespace Render +} // namespace Qt3DRender + +QT_END_NAMESPACE diff --git a/src/plugins/renderers/opengl/jobs/renderviewbuilderjob_p.h b/src/plugins/renderers/opengl/renderer/gllights_p.h index 13e19daf7..90fa91588 100644 --- a/src/plugins/renderers/opengl/jobs/renderviewbuilderjob_p.h +++ b/src/plugins/renderers/opengl/renderer/gllights_p.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB). +** Copyright (C) 2020 Klaralvdalens Datakonsult AB (KDAB). ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the Qt3D module of the Qt Toolkit. @@ -37,66 +37,52 @@ ** ****************************************************************************/ -#ifndef QT3DRENDER_RENDER_OPENGL_RENDERVIEWCOMMANDBUILDERJOB_P_H -#define QT3DRENDER_RENDER_OPENGL_RENDERVIEWCOMMANDBUILDERJOB_P_H +#ifndef QT3DRENDER_RENDER_OPENGL_GLLIGHTS_P_H +#define QT3DRENDER_RENDER_OPENGL_GLLIGHTS_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 <Qt3DCore/qaspectjob.h> -#include <Qt3DRender/private/handle_types_p.h> -#include <rendercommand_p.h> +#include <QString> QT_BEGIN_NAMESPACE namespace Qt3DRender { - namespace Render { - namespace OpenGL { -class RenderView; - -class Q_AUTOTEST_EXPORT RenderViewCommandBuilderJob : public Qt3DCore::QAspectJob -{ -public: - RenderViewCommandBuilderJob(); - - inline void setRenderView(RenderView *rv) Q_DECL_NOTHROW { m_renderView = rv; } - inline void setEntities(const QVector<Entity *> &entities, int offset, int count) - { - m_offset = offset; - m_count = count; - m_entities = entities; - } - inline EntityRenderCommandData &commandData() { return m_commandData; } +#define MAX_LIGHTS 8 - void run() final; +static_assert (MAX_LIGHTS < 10, "GL_Lights can't use the QChar trick anymore"); -private: - int m_offset; - int m_count; - RenderView *m_renderView; - QVector<Entity *> m_entities; - EntityRenderCommandData m_commandData; +struct GLLights +{ + static int LIGHT_COUNT_NAME_ID; + + static QString LIGHT_STRUCT_NAMES[MAX_LIGHTS]; + static int LIGHT_POSITION_NAMES[MAX_LIGHTS]; + static int LIGHT_TYPE_NAMES[MAX_LIGHTS]; + static int LIGHT_COLOR_NAMES[MAX_LIGHTS]; + static int LIGHT_INTENSITY_NAMES[MAX_LIGHTS]; + static int LIGHT_DIRECTION_NAMES[MAX_LIGHTS]; + static int LIGHT_LINEAR_ATTENUATION_NAMES[MAX_LIGHTS]; + static int LIGHT_QUADRATIC_ATTENUATION_NAMES[MAX_LIGHTS]; + static int LIGHT_CONSTANT_ATTENUATION_NAMES[MAX_LIGHTS]; + static int LIGHT_CUT_OFF_ANGLE_NAMES[MAX_LIGHTS]; + + static QString LIGHT_STRUCT_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_POSITION_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_TYPE_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_COLOR_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_INTENSITY_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_DIRECTION_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_LINEAR_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_CONSTANT_ATTENUATION_UNROLL_NAMES[MAX_LIGHTS]; + static int LIGHT_CUT_OFF_ANGLE_UNROLL_NAMES[MAX_LIGHTS]; }; -typedef QSharedPointer<RenderViewCommandBuilderJob> RenderViewCommandBuilderJobPtr; - -} // OpenGL - -} // Render - -} // Qt3DRender +} // namespace OpenGL +} // namespace Render +} // namespace Qt3DRender QT_END_NAMESPACE -#endif // QT3DRENDER_RENDER_OPENGL_RENDERVIEWCOMMANDBUILDERJOB_P_H +#endif // QT3DRENDER_RENDER_OPENGL_GLLIGHTS_P_H diff --git a/src/plugins/renderers/opengl/renderer/glshader.cpp b/src/plugins/renderers/opengl/renderer/glshader.cpp index 5e92d84c2..564e78a8e 100644 --- a/src/plugins/renderers/opengl/renderer/glshader.cpp +++ b/src/plugins/renderers/opengl/renderer/glshader.cpp @@ -42,6 +42,7 @@ #include <Qt3DRender/private/stringtoint_p.h> #include <graphicscontext_p.h> #include <logging_p.h> +#include <gllights_p.h> QT_BEGIN_NAMESPACE @@ -51,9 +52,51 @@ namespace Render { namespace OpenGL { +namespace { + +QVector<int> getLightUniformNameIds() +{ + QVector<int> names; + names.reserve(MAX_LIGHTS * 18 + 1); + + names << GLLights::LIGHT_COUNT_NAME_ID; + for (int i = 0; i < MAX_LIGHTS; ++i) { + names << GLLights::LIGHT_TYPE_NAMES[i] + << GLLights::LIGHT_COLOR_NAMES[i] + << GLLights::LIGHT_POSITION_NAMES[i] + << GLLights::LIGHT_INTENSITY_NAMES[i] + << GLLights::LIGHT_DIRECTION_NAMES[i] + << GLLights::LIGHT_LINEAR_ATTENUATION_NAMES[i] + << GLLights::LIGHT_QUADRATIC_ATTENUATION_NAMES[i] + << GLLights::LIGHT_CONSTANT_ATTENUATION_NAMES[i] + << GLLights::LIGHT_CUT_OFF_ANGLE_NAMES[i] + << GLLights::LIGHT_TYPE_UNROLL_NAMES[i] + << GLLights::LIGHT_COLOR_UNROLL_NAMES[i] + << GLLights::LIGHT_POSITION_UNROLL_NAMES[i] + << GLLights::LIGHT_INTENSITY_UNROLL_NAMES[i] + << GLLights::LIGHT_DIRECTION_UNROLL_NAMES[i] + << GLLights::LIGHT_LINEAR_ATTENUATION_UNROLL_NAMES[i] + << GLLights::LIGHT_QUADRATIC_ATTENUATION_UNROLL_NAMES[i] + << GLLights::LIGHT_CONSTANT_ATTENUATION_UNROLL_NAMES[i] + << GLLights::LIGHT_CUT_OFF_ANGLE_UNROLL_NAMES[i]; + } + + return names; +} + +template<typename Vector> +bool fastContains(const Vector &v, int value) +{ + return std::binary_search(v.cbegin(), v.cend(), value); +} + +} + GLShader::GLShader() : m_isLoaded(false) , m_graphicsContext(nullptr) + , m_parameterPackSize(0) + , m_hasActiveVariables(false) { m_shaderCode.resize(static_cast<int>(QShaderProgram::Compute) + 1); } @@ -106,7 +149,7 @@ QHash<QString, ShaderUniform> GLShader::activeUniformsForUniformBlock(int blockI return m_uniformBlockIndexToShaderUniforms.value(blockIndex); } -ShaderUniformBlock GLShader::uniformBlockForBlockIndex(int blockIndex) +ShaderUniformBlock GLShader::uniformBlockForBlockIndex(int blockIndex) const noexcept { for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) { if (m_uniformBlocks[i].m_index == blockIndex) { @@ -116,7 +159,7 @@ ShaderUniformBlock GLShader::uniformBlockForBlockIndex(int blockIndex) return ShaderUniformBlock(); } -ShaderUniformBlock GLShader::uniformBlockForBlockNameId(int blockNameId) +ShaderUniformBlock GLShader::uniformBlockForBlockNameId(int blockNameId) const noexcept { for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) { if (m_uniformBlocks[i].m_nameId == blockNameId) { @@ -126,7 +169,7 @@ ShaderUniformBlock GLShader::uniformBlockForBlockNameId(int blockNameId) return ShaderUniformBlock(); } -ShaderUniformBlock GLShader::uniformBlockForBlockName(const QString &blockName) +ShaderUniformBlock GLShader::uniformBlockForBlockName(const QString &blockName) const noexcept { for (int i = 0, m = m_uniformBlocks.size(); i < m; ++i) { if (m_uniformBlocks[i].m_name == blockName) { @@ -136,7 +179,7 @@ ShaderUniformBlock GLShader::uniformBlockForBlockName(const QString &blockName) return ShaderUniformBlock(); } -ShaderStorageBlock GLShader::storageBlockForBlockIndex(int blockIndex) +ShaderStorageBlock GLShader::storageBlockForBlockIndex(int blockIndex) const noexcept { for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) { if (m_shaderStorageBlocks[i].m_index == blockIndex) @@ -145,7 +188,7 @@ ShaderStorageBlock GLShader::storageBlockForBlockIndex(int blockIndex) return ShaderStorageBlock(); } -ShaderStorageBlock GLShader::storageBlockForBlockNameId(int blockNameId) +ShaderStorageBlock GLShader::storageBlockForBlockNameId(int blockNameId) const noexcept { for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) { if (m_shaderStorageBlocks[i].m_nameId == blockNameId) @@ -154,7 +197,7 @@ ShaderStorageBlock GLShader::storageBlockForBlockNameId(int blockNameId) return ShaderStorageBlock(); } -ShaderStorageBlock GLShader::storageBlockForBlockName(const QString &blockName) +ShaderStorageBlock GLShader::storageBlockForBlockName(const QString &blockName) const noexcept { for (int i = 0, m = m_shaderStorageBlockNames.size(); i < m; ++i) { if (m_shaderStorageBlocks[i].m_name == blockName) @@ -163,6 +206,22 @@ ShaderStorageBlock GLShader::storageBlockForBlockName(const QString &blockName) return ShaderStorageBlock(); } +GLShader::ParameterKind GLShader::categorizeVariable(int nameId) const noexcept +{ + if (fastContains(m_uniformsNamesIds, nameId)) + return ParameterKind::Uniform; + if (fastContains(m_uniformBlockNamesIds, nameId)) + return ParameterKind::UBO; + if (fastContains(m_shaderStorageBlockNamesIds, nameId)) + return ParameterKind::SSBO; + return ParameterKind::Struct; +} + +bool GLShader::hasUniform(int nameId) const noexcept +{ + return m_uniformsNamesIds.contains(nameId); +} + void GLShader::prepareUniforms(ShaderParameterPack &pack) { const PackUniformHash &values = pack.uniforms(); @@ -170,14 +229,20 @@ void GLShader::prepareUniforms(ShaderParameterPack &pack) auto it = values.keys.cbegin(); const auto end = values.keys.cend(); + const int shaderUniformsCount = m_uniforms.size(); + const auto uIt = m_uniforms.cbegin(); + while (it != end) { // Find if there's a uniform with the same name id - for (const ShaderUniform &uniform : qAsConst(m_uniforms)) { - if (uniform.m_nameId == *it) { - pack.setSubmissionUniform(uniform); - break; - } - } + + int i = 0; + const int targetNameId = *it; + while (i < shaderUniformsCount && (uIt + i)->m_nameId < targetNameId) + ++i; + + if (i < shaderUniformsCount && (uIt + i)->m_nameId == targetNameId) + pack.setSubmissionUniformIndex(i); + ++it; } } @@ -188,7 +253,6 @@ void GLShader::setFragOutputs(const QHash<QString, int> &fragOutputs) QMutexLocker lock(&m_mutex); m_fragOutputs = fragOutputs; } -// updateDNA(); } const QHash<QString, int> GLShader::fragOutputs() const @@ -203,6 +267,7 @@ void GLShader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescript m_uniformsNames.resize(uniformsDescription.size()); m_uniformsNamesIds.reserve(uniformsDescription.size()); m_standardUniformNamesIds.reserve(5); + m_lightUniformsNamesIds.reserve(MAX_LIGHTS * 8 + 1); QHash<QString, ShaderUniform> activeUniformsInDefaultBlock; static const QVector<int> standardUniformNameIds = { @@ -231,14 +296,18 @@ void GLShader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescript Shader::skinningPaletteNameId, }; + static const QVector<int> lightUniformNameIds = getLightUniformNameIds(); + for (int i = 0, m = uniformsDescription.size(); i < m; i++) { m_uniformsNames[i] = m_uniforms[i].m_name; const int nameId = StringToInt::lookupId(m_uniformsNames[i]); m_uniforms[i].m_nameId = nameId; - // Is the uniform a Qt3D "Standard" uniform or a user defined one? + // Is the uniform a Qt3D "Standard" uniform, a light uniform or a user defined one? if (standardUniformNameIds.contains(nameId)) m_standardUniformNamesIds.push_back(nameId); + else if (lightUniformNameIds.contains(nameId)) + m_lightUniformsNamesIds.push_back(nameId); else m_uniformsNamesIds.push_back(nameId); @@ -248,6 +317,18 @@ void GLShader::initializeUniforms(const QVector<ShaderUniform> &uniformsDescript } } m_uniformBlockIndexToShaderUniforms.insert(-1, activeUniformsInDefaultBlock); + + m_parameterPackSize += m_standardUniformNamesIds.size() + m_lightUniformsNamesIds.size() + m_uniformsNamesIds.size(); + m_hasActiveVariables |= (m_parameterPackSize > 0); + + // Sort by ascending order to make contains check faster + std::sort(m_uniformsNamesIds.begin(), m_uniformsNamesIds.end()); + std::sort(m_lightUniformsNamesIds.begin(), m_lightUniformsNamesIds.end()); + std::sort(m_standardUniformNamesIds.begin(), m_standardUniformNamesIds.end()); + std::sort(m_uniforms.begin(), m_uniforms.end(), + [] (const ShaderUniform &a, const ShaderUniform &b) { + return a.m_nameId < b.m_nameId; + }); } void GLShader::initializeAttributes(const QVector<ShaderAttribute> &attributesDescription) @@ -261,6 +342,7 @@ void GLShader::initializeAttributes(const QVector<ShaderAttribute> &attributesDe m_attributeNamesIds[i] = m_attributes[i].m_nameId; qCDebug(Shaders) << "Active Attribute " << attributesDescription[i].m_name; } + m_hasActiveVariables |= (m_attributeNamesIds.size() > 0); } void GLShader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &uniformBlockDescription) @@ -296,6 +378,12 @@ void GLShader::initializeUniformBlocks(const QVector<ShaderUniformBlock> &unifor } m_uniformBlockIndexToShaderUniforms.insert(uniformBlockDescription[i].m_index, activeUniformsInBlock); } + + m_parameterPackSize += m_uniformsNamesIds.size(); + m_hasActiveVariables |= (m_parameterPackSize > 0); + + // Sort by ascending order to make contains check faster + std::sort(m_uniformBlockNamesIds.begin(), m_uniformBlockNamesIds.end()); } void GLShader::initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &shaderStorageBlockDescription) @@ -310,6 +398,12 @@ void GLShader::initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> & m_shaderStorageBlocks[i].m_nameId =m_shaderStorageBlockNamesIds[i]; qCDebug(Shaders) << "Initializing Shader Storage Block {" << m_shaderStorageBlockNames[i] << "}"; } + + m_parameterPackSize += m_shaderStorageBlockNamesIds.size(); + m_hasActiveVariables |= (m_parameterPackSize > 0); + + // Sort by ascending order to make contains check faster + std::sort(m_shaderStorageBlockNamesIds.begin(), m_shaderStorageBlockNamesIds.end()); } } // OpenGL diff --git a/src/plugins/renderers/opengl/renderer/glshader_p.h b/src/plugins/renderers/opengl/renderer/glshader_p.h index 6bd5400af..ae447cd18 100644 --- a/src/plugins/renderers/opengl/renderer/glshader_p.h +++ b/src/plugins/renderers/opengl/renderer/glshader_p.h @@ -57,6 +57,9 @@ #include <Qt3DRender/qshaderprogram.h> #include <QMutex> +#ifdef QT_BUILD_INTERNAL + class tst_BenchShaderParameterPack; +#endif QT_BEGIN_NAMESPACE @@ -84,31 +87,44 @@ public: void setFragOutputs(const QHash<QString, int> &fragOutputs); const QHash<QString, int> fragOutputs() const; - inline QVector<int> uniformsNamesIds() const { return m_uniformsNamesIds; } - inline QVector<int> standardUniformNameIds() const { return m_standardUniformNamesIds; } - inline QVector<int> uniformBlockNamesIds() const { return m_uniformBlockNamesIds; } - inline QVector<int> storageBlockNamesIds() const { return m_shaderStorageBlockNamesIds; } - inline QVector<int> attributeNamesIds() const { return m_attributeNamesIds; } + inline const QVector<int> &uniformsNamesIds() const { return m_uniformsNamesIds; } + inline const QVector<int> &lightUniformsNamesIds() const { return m_lightUniformsNamesIds; } + inline const QVector<int> &standardUniformNameIds() const { return m_standardUniformNamesIds; } + inline const QVector<int> &uniformBlockNamesIds() const { return m_uniformBlockNamesIds; } + inline const QVector<int> &storageBlockNamesIds() const { return m_shaderStorageBlockNamesIds; } + inline const QVector<int> &attributeNamesIds() const { return m_attributeNamesIds; } QVector<QString> uniformsNames() const; QVector<QString> attributesNames() const; QVector<QString> uniformBlockNames() const; QVector<QString> storageBlockNames() const; - inline QVector<ShaderUniform> uniforms() const { return m_uniforms; } - inline QVector<ShaderAttribute> attributes() const { return m_attributes; } - inline QVector<ShaderUniformBlock> uniformBlocks() const { return m_uniformBlocks; } - inline QVector<ShaderStorageBlock> storageBlocks() const { return m_shaderStorageBlocks; } + inline const QVector<ShaderUniform> &uniforms() const { return m_uniforms; } + inline const QVector<ShaderAttribute> &attributes() const { return m_attributes; } + inline const QVector<ShaderUniformBlock> &uniformBlocks() const { return m_uniformBlocks; } + inline const QVector<ShaderStorageBlock> &storageBlocks() const { return m_shaderStorageBlocks; } QHash<QString, ShaderUniform> activeUniformsForUniformBlock(int blockIndex) const; - ShaderUniformBlock uniformBlockForBlockIndex(int blockNameId); - ShaderUniformBlock uniformBlockForBlockNameId(int blockIndex); - ShaderUniformBlock uniformBlockForBlockName(const QString &blockName); + ShaderUniformBlock uniformBlockForBlockIndex(int blockNameId) const noexcept; + ShaderUniformBlock uniformBlockForBlockNameId(int blockIndex) const noexcept; + ShaderUniformBlock uniformBlockForBlockName(const QString &blockName) const noexcept; - ShaderStorageBlock storageBlockForBlockIndex(int blockIndex); - ShaderStorageBlock storageBlockForBlockNameId(int blockNameId); - ShaderStorageBlock storageBlockForBlockName(const QString &blockName); + ShaderStorageBlock storageBlockForBlockIndex(int blockIndex) const noexcept; + ShaderStorageBlock storageBlockForBlockNameId(int blockNameId) const noexcept; + ShaderStorageBlock storageBlockForBlockName(const QString &blockName) const noexcept; + + enum ParameterKind { + Uniform, + UBO, + SSBO, + Struct + }; + ParameterKind categorizeVariable(int nameId) const noexcept; + + bool hasUniform(int nameId) const noexcept; + inline bool hasActiveVariables() const noexcept { return m_hasActiveVariables; } + inline int parameterPackSize() const noexcept { return m_parameterPackSize; } QOpenGLShaderProgram *shaderProgram() { return &m_shader; } @@ -122,6 +138,7 @@ private: QVector<QString> m_uniformsNames; QVector<int> m_uniformsNamesIds; + QVector<int> m_lightUniformsNamesIds; QVector<int> m_standardUniformNamesIds; QVector<ShaderUniform> m_uniforms; @@ -141,6 +158,9 @@ private: QHash<QString, int> m_fragOutputs; QVector<QByteArray> m_shaderCode; + int m_parameterPackSize; + int m_hasActiveVariables; + // Private so that only GraphicContext can call it void initializeUniforms(const QVector<ShaderUniform> &uniformsDescription); void initializeAttributes(const QVector<ShaderAttribute> &attributesDescription); @@ -148,6 +168,9 @@ private: void initializeShaderStorageBlocks(const QVector<ShaderStorageBlock> &shaderStorageBlockDescription); friend class GraphicsContext; +#ifdef QT_BUILD_INTERNAL + friend class ::tst_BenchShaderParameterPack; +#endif mutable QMutex m_mutex; QMetaObject::Connection m_contextConnection; diff --git a/src/plugins/renderers/opengl/renderer/renderer.cpp b/src/plugins/renderers/opengl/renderer/renderer.cpp index 3ad9c2818..57ee5ec88 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.cpp +++ b/src/plugins/renderers/opengl/renderer/renderer.cpp @@ -995,16 +995,9 @@ void Renderer::prepareCommandsSubmission(const QVector<RenderView *> &renderView // 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); - } else if (command.m_type == RenderCommand::Compute) { GLShader *shader = command.m_glShader; Q_ASSERT(shader); - - // Prepare the ShaderParameterPack based on the active uniforms of the shader - shader->prepareUniforms(command.m_parameterPack); } } } @@ -1172,6 +1165,10 @@ void Renderer::sendShaderChangesToFrontend(Qt3DCore::QAspectManager *manager) Shader *s = m_nodesManager->shaderManager()->data(handle); if (s->requiresFrontendSync()) { QShaderProgram *frontend = static_cast<decltype(frontend)>(manager->lookupNode(s->peerId())); + // Could happen as a backend shader might live beyong the frontend + // the time needed to destroy the GLShader assoicated with it. + if (!frontend) + continue; QShaderProgramPrivate *dFrontend = static_cast<decltype(dFrontend)>(QNodePrivate::get(frontend)); s->unsetRequiresFrontendSync(); dFrontend->setStatus(s->status()); @@ -1917,10 +1914,31 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs() m_updatedDisableSubtreeEnablers.push_back(node->peerId()); } + int idealThreadCount = QThread::idealThreadCount(); + const QByteArray maxThreadCount = qgetenv("QT3D_MAX_THREAD_COUNT"); + if (!maxThreadCount.isEmpty()) { + bool conversionOK = false; + const int maxThreadCountValue = maxThreadCount.toInt(&conversionOK); + if (conversionOK) + idealThreadCount = maxThreadCountValue; + } + const int fgBranchCount = m_frameGraphLeaves.size(); + if (fgBranchCount > 1) { + int workBranches = fgBranchCount; + for (auto leaf: qAsConst(m_frameGraphLeaves)) + if (leaf->nodeType() == FrameGraphNode::NoDraw) + --workBranches; + + if (idealThreadCount > 4 && workBranches && maxThreadCount.isEmpty()) + idealThreadCount = qMax(4, idealThreadCount / workBranches); + } + for (int i = 0; i < fgBranchCount; ++i) { FrameGraphNode *leaf = m_frameGraphLeaves.at(i); RenderViewBuilder builder(leaf, i, this); + builder.setOptimalJobCount(leaf->nodeType() == FrameGraphNode::NoDraw ? 1 : idealThreadCount); + // If we have a new RV (wasn't in the cache before, then it contains no cached data) const bool isNewRV = !m_cache.leafNodeCache.contains(leaf); builder.setLayerCacheNeedsToBeRebuilt(layersCacheNeedsToBeRebuilt || isNewRV); @@ -2046,7 +2064,7 @@ void Renderer::performCompute(const RenderView *, RenderCommand *command) } { Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate, activeProfiler()); - m_submissionContext->setParameters(command->m_parameterPack); + m_submissionContext->setParameters(command->m_parameterPack, command->m_glShader); } { Profiling::GLTimeRecorder recorder(Profiling::DispatchCompute, activeProfiler()); @@ -2140,7 +2158,7 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv) { Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate, activeProfiler()); //// Update program uniforms - if (!m_submissionContext->setParameters(command.m_parameterPack)) { + if (!m_submissionContext->setParameters(command.m_parameterPack, command.m_glShader)) { 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 diff --git a/src/plugins/renderers/opengl/renderer/renderer.pri b/src/plugins/renderers/opengl/renderer/renderer.pri index 3e3f83c86..1a0240e77 100644 --- a/src/plugins/renderers/opengl/renderer/renderer.pri +++ b/src/plugins/renderers/opengl/renderer/renderer.pri @@ -1,6 +1,7 @@ INCLUDEPATH += $$PWD SOURCES += \ + $$PWD/gllights.cpp \ $$PWD/openglvertexarrayobject.cpp \ $$PWD/rendercommand.cpp \ $$PWD/renderer.cpp \ @@ -13,6 +14,7 @@ SOURCES += \ $$PWD/commandexecuter.cpp HEADERS += \ + $$PWD/gllights_p.h \ $$PWD/openglvertexarrayobject_p.h \ $$PWD/renderercache_p.h \ $$PWD/rendercommand_p.h \ diff --git a/src/plugins/renderers/opengl/renderer/renderer_p.h b/src/plugins/renderers/opengl/renderer/renderer_p.h index 8cf610efb..d4980464a 100644 --- a/src/plugins/renderers/opengl/renderer/renderer_p.h +++ b/src/plugins/renderers/opengl/renderer/renderer_p.h @@ -173,7 +173,7 @@ public: ~Renderer(); void dumpInfo() const override; - API api() const override { return AbstractRenderer::OpenGL; } + API api() const override { return Qt3DRender::API::OpenGL; } qint64 time() const override; void setTime(qint64 time) override; @@ -270,7 +270,7 @@ public: QSharedPointer<RenderBackendResourceAccessor> resourceAccessor() const override; - const GraphicsApiFilterData *contextInfo() const; + const GraphicsApiFilterData *contextInfo() const override; SubmissionContext *submissionContext() const; inline RenderStateSet *defaultRenderState() const { return m_defaultRenderStateSet; } diff --git a/src/plugins/renderers/opengl/renderer/renderview.cpp b/src/plugins/renderers/opengl/renderer/renderview.cpp index 99ac88a94..a3a00782e 100644 --- a/src/plugins/renderers/opengl/renderer/renderview.cpp +++ b/src/plugins/renderers/opengl/renderer/renderview.cpp @@ -75,7 +75,8 @@ #include <Qt3DCore/qentity.h> #include <QtGui/qsurface.h> #include <algorithm> - +#include <atomic> +#include <gllights_p.h> #include <QDebug> #if defined(QT3D_RENDER_VIEW_JOB_TIMINGS) #include <QElapsedTimer> @@ -87,33 +88,12 @@ namespace Qt3DRender { namespace Render { namespace OpenGL { - 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]; - -int LIGHT_POSITION_UNROLL_NAMES[MAX_LIGHTS]; -int LIGHT_TYPE_UNROLL_NAMES[MAX_LIGHTS]; -int LIGHT_COLOR_UNROLL_NAMES[MAX_LIGHTS]; -int LIGHT_INTENSITY_UNROLL_NAMES[MAX_LIGHTS]; -QString LIGHT_STRUCT_UNROLL_NAMES[MAX_LIGHTS]; - -bool wasInitialized = false; +std::atomic_bool wasInitialized{}; } // anonymous namespace @@ -168,9 +148,10 @@ static Matrix4x4 getProjectionMatrix(const CameraLens *lens) } UniformValue RenderView::standardUniformValue(RenderView::StandardUniform standardUniformType, - Entity *entity, - const Matrix4x4 &model) const + const Entity *entity) const { + const Matrix4x4 &model = *(entity->worldTransform()); + switch (standardUniformType) { case ModelMatrix: return UniformValue(model); @@ -263,26 +244,11 @@ RenderView::RenderView() m_workGroups[1] = 1; m_workGroups[2] = 1; - if (Q_UNLIKELY(!wasInitialized)) { + if (Q_UNLIKELY(!wasInitialized.exchange(true))) { // 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); - - LIGHT_STRUCT_UNROLL_NAMES[i] = QLatin1String("light_") + QLatin1Char(char('0' + i)); - LIGHT_POSITION_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_POSITION_NAME); - LIGHT_TYPE_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_TYPE_NAME); - LIGHT_COLOR_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_COLOR_NAME); - LIGHT_INTENSITY_UNROLL_NAMES[i] = StringToInt::lookupId(LIGHT_STRUCT_UNROLL_NAMES[i] + LIGHT_INTENSITY_NAME); - } } } @@ -437,6 +403,7 @@ struct SubRangeSorter<QSortPolicy::Texture> { static void sortSubRange(CommandIt begin, const CommandIt end) { +#ifndef Q_OS_WIN std::stable_sort(begin, end, [] (const RenderCommand &a, const RenderCommand &b) { QVector<ShaderParameterPack::NamedResource> texturesA = a.m_parameterPack.textures(); QVector<ShaderParameterPack::NamedResource> texturesB = b.m_parameterPack.textures(); @@ -455,6 +422,7 @@ struct SubRangeSorter<QSortPolicy::Texture> return identicalTextureCount < originalTextureASize; }); +#endif } }; @@ -958,21 +926,16 @@ void RenderView::setUniformValue(ShaderParameterPack &uniformPack, int nameId, c } void RenderView::setStandardUniformValue(ShaderParameterPack &uniformPack, - int glslNameId, int nameId, - Entity *entity, - const Matrix4x4 &worldTransform) const + const Entity *entity) const { - uniformPack.setUniform(glslNameId, standardUniformValue(ms_standardUniformSetters[nameId], entity, worldTransform)); + uniformPack.setUniform(nameId, standardUniformValue(ms_standardUniformSetters[nameId], entity)); } void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, - GLShader *shader, const ShaderUniformBlock &block, const UniformValue &value) const { - Q_UNUSED(shader) - if (value.valueType() == UniformValue::NodeId) { Buffer *buffer = nullptr; @@ -988,11 +951,9 @@ void RenderView::setUniformBlockValue(ShaderParameterPack &uniformPack, } void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, - GLShader *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) { @@ -1006,7 +967,10 @@ void RenderView::setShaderStorageValue(ShaderParameterPack &uniformPack, } } -void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, GLShader *shader, ShaderData *shaderData, const QString &structName) const +void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, + const GLShader *shader, + const ShaderData *shaderData, + const QString &structName) const { UniformBlockValueBuilder *builder = m_localData.localData(); builder->activeUniformNamesToValue.clear(); @@ -1030,6 +994,42 @@ void RenderView::setDefaultUniformBlockShaderDataValue(ShaderParameterPack &unif } } +void RenderView::applyParameter(const Parameter *param, + RenderCommand *command, + const GLShader *shader) const noexcept +{ + const int nameId = param->nameId(); + const UniformValue &uniformValue = param->uniformValue(); + const GLShader::ParameterKind kind = shader->categorizeVariable(nameId); + + switch (kind) { + case GLShader::Uniform: { + setUniformValue(command->m_parameterPack, nameId, uniformValue); + break; + } + case GLShader::UBO: { + setUniformBlockValue(command->m_parameterPack, shader->uniformBlockForBlockNameId(nameId), uniformValue); + break; + } + case GLShader::SSBO: { + setShaderStorageValue(command->m_parameterPack, shader->storageBlockForBlockNameId(nameId), uniformValue); + break; + } + case GLShader::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(nameId)); + } + break; + } + default: + break; + } +} + + void RenderView::setShaderAndUniforms(RenderCommand *command, ParameterInfoList ¶meters, Entity *entity, @@ -1052,11 +1052,6 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, // 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> standardUniformNamesIds = shader->standardUniformNameIds(); - 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 @@ -1073,113 +1068,95 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, shader->setFragOutputs(fragOutputs); } - if (!uniformNamesIds.isEmpty() || !standardUniformNamesIds.isEmpty() || - !attributeNamesIds.isEmpty() || - !shaderStorageBlockNamesIds.isEmpty() || !attributeNamesIds.isEmpty()) { + // Set default attributes + command->m_activeAttributes = shader->attributeNamesIds(); - // Set default standard uniforms without bindings - const Matrix4x4 worldTransform = *(entity->worldTransform()); + // At this point we know whether the command is a valid draw command or not + // We still need to process the uniforms as the command could be a compute command + command->m_isValid = !command->m_activeAttributes.empty(); - for (const int uniformNameId : standardUniformNamesIds) - setStandardUniformValue(command->m_parameterPack, uniformNameId, uniformNameId, entity, worldTransform); - - // Set default attributes - command->m_activeAttributes = attributeNamesIds; + if (shader->hasActiveVariables()) { - // At this point we know whether the command is a valid draw command or not - // We still need to process the uniforms as the command could be a compute command - command->m_isValid = !command->m_activeAttributes.empty(); + // Reserve amount of uniforms we are going to need + command->m_parameterPack.reserve(shader->parameterPackSize()); - // Parameters remaining could be - // -> uniform scalar / vector - // -> uniform struct / arrays - // -> uniform block / array (4.3) - // -> ssbo block / array (4.3) + const QVector<int> &standardUniformNamesIds = shader->standardUniformNameIds(); + for (const int uniformNameId : standardUniformNamesIds) + setStandardUniformValue(command->m_parameterPack, uniformNameId, entity); 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 - } + const Parameter *param = m_manager->data<Parameter, ParameterManager>(it->handle); + applyParameter(param, command, shader); ++it; } // Lights - - int lightIdx = 0; - for (const LightSource &lightSource : activeLightSources) { - if (lightIdx == MAX_LIGHTS) - break; - Entity *lightEntity = lightSource.entity; - const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform()); - const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f); - for (Light *light : lightSource.lights) { - if (!light->isEnabled()) - continue; - - ShaderData *shaderData = m_manager->shaderDataManager()->lookupResource(light->shaderData()); - if (!shaderData) - continue; - + const QVector<int> &lightUniformNamesIds = shader->lightUniformsNamesIds(); + if (!lightUniformNamesIds.empty()) { + int lightIdx = 0; + for (const LightSource &lightSource : activeLightSources) { if (lightIdx == MAX_LIGHTS) break; + Entity *lightEntity = lightSource.entity; + const Matrix4x4 lightWorldTransform = *(lightEntity->worldTransform()); + const Vector3D worldPos = lightWorldTransform * Vector3D(0.0f, 0.0f, 0.0f); + 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); - - setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos); - setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f)); - setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_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]); - setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, LIGHT_STRUCT_UNROLL_NAMES[lightIdx]); - ++lightIdx; + // Note: implicit conversion of values to UniformValue + if (lightUniformNamesIds.contains(GLLights::LIGHT_TYPE_NAMES[lightIdx])) { + setUniformValue(command->m_parameterPack, GLLights::LIGHT_POSITION_NAMES[lightIdx], worldPos); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_TYPE_NAMES[lightIdx], int(QAbstractLight::PointLight)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_COLOR_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_INTENSITY_NAMES[lightIdx], 0.5f); + } else if (lightUniformNamesIds.contains(GLLights::LIGHT_TYPE_UNROLL_NAMES[lightIdx])) { + setUniformValue(command->m_parameterPack, GLLights::LIGHT_POSITION_UNROLL_NAMES[lightIdx], worldPos); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_TYPE_UNROLL_NAMES[lightIdx], int(QAbstractLight::PointLight)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_COLOR_UNROLL_NAMES[lightIdx], Vector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_INTENSITY_UNROLL_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, GLLights::LIGHT_STRUCT_NAMES[lightIdx]); + setDefaultUniformBlockShaderDataValue(command->m_parameterPack, shader, shaderData, GLLights::LIGHT_STRUCT_UNROLL_NAMES[lightIdx]); + ++lightIdx; + } } - } - if (uniformNamesIds.contains(LIGHT_COUNT_NAME_ID)) - setUniformValue(command->m_parameterPack, LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 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); - - setUniformValue(command->m_parameterPack, LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f)); - setUniformValue(command->m_parameterPack, LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight)); - setUniformValue(command->m_parameterPack, LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f)); - setUniformValue(command->m_parameterPack, LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_COUNT_NAME_ID, UniformValue(qMax((environmentLight ? 0 : 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 + if (lightUniformNamesIds.contains(GLLights::LIGHT_TYPE_NAMES[0])) { + setUniformValue(command->m_parameterPack, GLLights::LIGHT_POSITION_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_TYPE_NAMES[0], int(QAbstractLight::PointLight)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_COLOR_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_INTENSITY_NAMES[0], 0.5f); + } else if (lightUniformNamesIds.contains(GLLights::LIGHT_TYPE_UNROLL_NAMES[lightIdx])) { + setUniformValue(command->m_parameterPack, GLLights::LIGHT_POSITION_UNROLL_NAMES[0], Vector3D(10.0f, 10.0f, 0.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_TYPE_UNROLL_NAMES[0], int(QAbstractLight::PointLight)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_COLOR_UNROLL_NAMES[0], Vector3D(1.0f, 1.0f, 1.0f)); + setUniformValue(command->m_parameterPack, GLLights::LIGHT_INTENSITY_UNROLL_NAMES[0], 0.5f); + } + } } // Environment Light @@ -1200,6 +1177,9 @@ void RenderView::setShaderAndUniforms(RenderCommand *command, } setUniformValue(command->m_parameterPack, StringToInt::lookupId(QStringLiteral("envLightCount")), envLightCount); } + + // Prepare the ShaderParameterPack based on the active uniforms of the shader + shader->prepareUniforms(command->m_parameterPack); } } @@ -1233,6 +1213,9 @@ bool RenderView::shouldSkipSubmission() const if (m_clearBuffer != QClearBuffers::None) return false; + if (!m_renderCaptureNodeId.isNull()) + return false; + return true; } diff --git a/src/plugins/renderers/opengl/renderer/renderview_p.h b/src/plugins/renderers/opengl/renderer/renderview_p.h index adab30f4e..6c41ce500 100644 --- a/src/plugins/renderers/opengl/renderer/renderview_p.h +++ b/src/plugins/renderers/opengl/renderer/renderview_p.h @@ -370,27 +370,25 @@ private: static StandardUniformsNameToTypeHash initializeStandardUniformSetters(); UniformValue standardUniformValue(StandardUniform standardUniformType, - Entity *entity, - const Matrix4x4 &model) const; + const Entity *entity) 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; + const Entity *entity) const; void setUniformBlockValue(ShaderParameterPack &uniformPack, - GLShader *shader, const ShaderUniformBlock &block, const UniformValue &value) const; void setShaderStorageValue(ShaderParameterPack &uniformPack, - GLShader *shader, const ShaderStorageBlock &block, const UniformValue &value) const; void setDefaultUniformBlockShaderDataValue(ShaderParameterPack &uniformPack, - GLShader *shader, - ShaderData *shaderData, + const GLShader *shader, + const ShaderData *shaderData, const QString &structName) const; + void applyParameter(const Parameter *param, + RenderCommand *command, + const GLShader *shader) const noexcept; }; } // namespace OpenGL diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp index 8ed32ff10..b0ac76199 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder.cpp @@ -49,18 +49,13 @@ namespace Qt3DRender { namespace Render { namespace OpenGL { -// In some cases having less jobs is better (especially on fast cpus where -// splitting just adds more overhead). Ideally, we should try to set the value -// depending on the platform/CPU/nbr of cores -const int RenderViewBuilder::m_optimalParallelJobCount = QThread::idealThreadCount(); - namespace { -int findIdealNumberOfWorkers(int elementCount, int packetSize = 100) +int findIdealNumberOfWorkers(int elementCount, int packetSize = 100, int maxJobCount = 1) { if (elementCount == 0 || packetSize == 0) return 0; - return std::min(std::max(elementCount / packetSize, 1), RenderViewBuilder::optimalJobCount()); + return std::min(std::max(elementCount / packetSize, 1), maxJobCount); } @@ -93,9 +88,10 @@ public: lock.unlock(); // Split among the ideal number of command builders - const int idealPacketSize = std::min(std::max(100, entities.size() / RenderViewBuilder::optimalJobCount()), entities.size()); + const int jobCount = m_renderViewCommandBuilderJobs.size(); + const int idealPacketSize = std::min(std::max(10, entities.size() / jobCount), entities.size()); // Try to split work into an ideal number of workers - const int m = findIdealNumberOfWorkers(entities.size(), idealPacketSize); + const int m = findIdealNumberOfWorkers(entities.size(), idealPacketSize, jobCount); for (int i = 0; i < m; ++i) { const RenderViewCommandBuilderJobPtr renderViewCommandBuilder = m_renderViewCommandBuilderJobs.at(i); @@ -352,9 +348,9 @@ public: } // Split among the number of command builders - // The idealPacketSize is at least 100 entities per worker - const int idealPacketSize = std::min(std::max(100, filteredCommandData->size() / RenderViewBuilder::optimalJobCount()), filteredCommandData->size()); - const int m = findIdealNumberOfWorkers(filteredCommandData->size(), idealPacketSize); + const int jobCount = m_renderViewCommandUpdaterJobs.size(); + const int idealPacketSize = std::min(std::max(10, filteredCommandData->size() / jobCount), filteredCommandData->size()); + const int m = findIdealNumberOfWorkers(filteredCommandData->size(), idealPacketSize, jobCount); for (int i = 0; i < m; ++i) { const RenderViewCommandUpdaterJobPtr renderViewCommandBuilder = m_renderViewCommandUpdaterJobs.at(i); @@ -474,6 +470,10 @@ RenderViewBuilder::RenderViewBuilder(Render::FrameGraphNode *leafNode, int rende , m_syncFilterEntityByLayerJob() , m_filterProximityJob(Render::FilterProximityDistanceJobPtr::create()) { + // In some cases having less jobs is better (especially on fast cpus where + // splitting just adds more overhead). Ideally, we should try to set the value + // depending on the platform/CPU/nbr of cores + m_optimalParallelJobCount = QThread::idealThreadCount(); } RenderViewInitializerJobPtr RenderViewBuilder::renderViewJob() const @@ -558,17 +558,16 @@ void RenderViewBuilder::prepareJobs() m_frustumCullingJob->setRoot(m_renderer->sceneRoot()); if (m_renderCommandCacheNeedsToBeRebuilt) { - - m_renderViewCommandBuilderJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount); - for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) { + m_renderViewCommandBuilderJobs.reserve(m_optimalParallelJobCount); + for (auto i = 0; i < m_optimalParallelJobCount; ++i) { auto renderViewCommandBuilder = Render::OpenGL::RenderViewCommandBuilderJobPtr::create(); m_renderViewCommandBuilderJobs.push_back(renderViewCommandBuilder); } m_syncRenderViewPreCommandBuildingJob = CreateSynchronizerJobPtr(SyncPreCommandBuilding(m_renderViewJob, - m_renderViewCommandBuilderJobs, - m_renderer, - m_leafNode), - JobTypes::SyncRenderViewPreCommandBuilding); + m_renderViewCommandBuilderJobs, + m_renderer, + m_leafNode), + JobTypes::SyncRenderViewPreCommandBuilding); } m_renderViewJob->setRenderer(m_renderer); @@ -577,8 +576,8 @@ void RenderViewBuilder::prepareJobs() // RenderCommand building is the most consuming task -> split it // Estimate the number of jobs to create based on the number of entities - m_renderViewCommandUpdaterJobs.reserve(RenderViewBuilder::m_optimalParallelJobCount); - for (auto i = 0; i < RenderViewBuilder::m_optimalParallelJobCount; ++i) { + m_renderViewCommandUpdaterJobs.reserve(m_optimalParallelJobCount); + for (auto i = 0; i < m_optimalParallelJobCount; ++i) { auto renderViewCommandUpdater = Render::OpenGL::RenderViewCommandUpdaterJobPtr::create(); renderViewCommandUpdater->setRenderer(m_renderer); m_renderViewCommandUpdaterJobs.push_back(renderViewCommandUpdater); @@ -587,22 +586,23 @@ void RenderViewBuilder::prepareJobs() 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 = MaterialParameterGathererJobPtr::create(); - materialGatherer->setNodeManagers(m_renderer->nodeManagers()); - 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); + if (materialHandles.count()) { + const int elementsPerJob = qMax(materialHandles.size() / m_optimalParallelJobCount, 1); + m_materialGathererJobs.reserve(m_optimalParallelJobCount); + int elementCount = 0; + while (elementCount < materialHandles.size()) { + auto materialGatherer = MaterialParameterGathererJobPtr::create(); + materialGatherer->setNodeManagers(m_renderer->nodeManagers()); + materialGatherer->setHandles(materialHandles.mid(elementCount, elementsPerJob)); + m_materialGathererJobs.push_back(materialGatherer); + + elementCount += elementsPerJob; + } } m_syncMaterialGathererJob = CreateSynchronizerJobPtr(SyncMaterialParameterGatherer(m_materialGathererJobs, - m_renderer, - m_leafNode), - JobTypes::SyncMaterialGatherer); + m_renderer, + m_leafNode), + JobTypes::SyncMaterialGatherer); } if (m_layerCacheNeedsToBeRebuilt) { @@ -615,29 +615,29 @@ void RenderViewBuilder::prepareJobs() } m_syncRenderViewPreCommandUpdateJob = CreateSynchronizerJobPtr(SyncRenderViewPreCommandUpdate(m_renderViewJob, - m_frustumCullingJob, - m_filterProximityJob, - m_materialGathererJobs, - m_renderViewCommandUpdaterJobs, - m_renderViewCommandBuilderJobs, - m_renderer, - m_leafNode, - m_renderCommandCacheNeedsToBeRebuilt), - JobTypes::SyncRenderViewPreCommandUpdate); + m_frustumCullingJob, + m_filterProximityJob, + m_materialGathererJobs, + m_renderViewCommandUpdaterJobs, + m_renderViewCommandBuilderJobs, + m_renderer, + m_leafNode, + m_renderCommandCacheNeedsToBeRebuilt), + JobTypes::SyncRenderViewPreCommandUpdate); m_syncRenderViewPostCommandUpdateJob = CreateSynchronizerJobPtr(SyncRenderViewPostCommandUpdate(m_renderViewJob, - m_renderViewCommandUpdaterJobs, - m_renderer), - JobTypes::SyncRenderViewPostCommandUpdate); + m_renderViewCommandUpdaterJobs, + m_renderer), + JobTypes::SyncRenderViewPostCommandUpdate); m_syncRenderViewPostInitializationJob = CreateSynchronizerJobPtr(SyncRenderViewPostInitialization(m_renderViewJob, - m_frustumCullingJob, - m_filterEntityByLayerJob, - m_filterProximityJob, - m_materialGathererJobs, - m_renderViewCommandUpdaterJobs, - m_renderViewCommandBuilderJobs), - JobTypes::SyncRenderViewInitialization); + m_frustumCullingJob, + m_filterEntityByLayerJob, + m_filterProximityJob, + m_materialGathererJobs, + m_renderViewCommandUpdaterJobs, + m_renderViewCommandBuilderJobs), + JobTypes::SyncRenderViewInitialization); } QVector<Qt3DCore::QAspectJobPtr> RenderViewBuilder::buildJobHierachy() const @@ -793,9 +793,34 @@ bool RenderViewBuilder::renderCommandCacheNeedsToBeRebuilt() const return m_renderCommandCacheNeedsToBeRebuilt; } -int RenderViewBuilder::optimalJobCount() +int RenderViewBuilder::defaultJobCount() +{ + static int jobCount = 0; + if (jobCount) + return jobCount; + + const QByteArray maxThreadCount = qgetenv("QT3D_MAX_THREAD_COUNT"); + if (!maxThreadCount.isEmpty()) { + bool conversionOK = false; + const int maxThreadCountValue = maxThreadCount.toInt(&conversionOK); + if (conversionOK) { + jobCount = maxThreadCountValue; + return jobCount; + } + } + + jobCount = QThread::idealThreadCount(); + return jobCount; +} + +int RenderViewBuilder::optimalJobCount() const +{ + return m_optimalParallelJobCount; +} + +void RenderViewBuilder::setOptimalJobCount(int v) { - return RenderViewBuilder::m_optimalParallelJobCount; + m_optimalParallelJobCount = v; } QVector<Entity *> RenderViewBuilder::entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset) diff --git a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h index 54fc98352..17e5fa744 100644 --- a/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h +++ b/src/plugins/renderers/opengl/renderer/renderviewbuilder_p.h @@ -61,7 +61,6 @@ #include <renderviewcommandbuilderjob_p.h> #include <renderviewcommandupdaterjob_p.h> #include <materialparametergathererjob_p.h> -#include <renderviewbuilderjob_p.h> #include <renderview_p.h> QT_BEGIN_NAMESPACE @@ -112,7 +111,10 @@ public: void setRenderCommandCacheNeedsToBeRebuilt(bool needsToBeRebuilt); bool renderCommandCacheNeedsToBeRebuilt() const; - static int optimalJobCount(); + static int defaultJobCount(); + int optimalJobCount() const; + void setOptimalJobCount(int v); + static QVector<Entity *> entitiesInSubset(const QVector<Entity *> &entities, const QVector<Entity *> &subset); private: @@ -140,7 +142,7 @@ private: SynchronizerJobPtr m_syncMaterialGathererJob; FilterProximityDistanceJobPtr m_filterProximityJob; - static const int m_optimalParallelJobCount; + int m_optimalParallelJobCount; }; } // OpenGL diff --git a/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp b/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp index c51595bb7..bc9e9434b 100644 --- a/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp +++ b/src/plugins/renderers/opengl/renderer/shaderparameterpack.cpp @@ -58,6 +58,12 @@ ShaderParameterPack::~ShaderParameterPack() { } +void ShaderParameterPack::reserve(int uniformCount) +{ + m_uniforms.reserve(uniformCount); + m_submissionUniformIndices.reserve(uniformCount); +} + void ShaderParameterPack::setUniform(const int glslNameId, const UniformValue &val) { m_uniforms.insert(glslNameId, val); @@ -100,9 +106,9 @@ void ShaderParameterPack::setShaderStorageBuffer(BlockToSSBO blockToSSBO) m_shaderStorageBuffers.push_back(std::move(blockToSSBO)); } -void ShaderParameterPack::setSubmissionUniform(const ShaderUniform &uniform) +void ShaderParameterPack::setSubmissionUniformIndex(const int uniformIdx) { - m_submissionUniforms.push_back(uniform); + m_submissionUniformIndices.push_back(uniformIdx); } } // namespace OpenGL diff --git a/src/plugins/renderers/opengl/renderer/shaderparameterpack_p.h b/src/plugins/renderers/opengl/renderer/shaderparameterpack_p.h index 31ef4f7ea..bb6bb0dc6 100644 --- a/src/plugins/renderers/opengl/renderer/shaderparameterpack_p.h +++ b/src/plugins/renderers/opengl/renderer/shaderparameterpack_p.h @@ -93,8 +93,12 @@ struct PackUniformHash PackUniformHash() { - keys.reserve(10); - values.reserve(10); + } + + void reserve(int count) + { + keys.reserve(count); + values.reserve(count); } void insert(int key, const UniformValue &value) @@ -142,13 +146,14 @@ class Q_AUTOTEST_EXPORT ShaderParameterPack public: ~ShaderParameterPack(); + void reserve(int uniformCount); void setUniform(const int glslNameId, const UniformValue &val); void setTexture(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); void setImage(const int glslNameId, int uniformArrayIndex, Qt3DCore::QNodeId id); void setUniformBuffer(BlockToUBO blockToUBO); void setShaderStorageBuffer(BlockToSSBO blockToSSBO); - void setSubmissionUniform(const ShaderUniform &uniform); + void setSubmissionUniformIndex(const int shaderUniformIndex); inline PackUniformHash &uniforms() { return m_uniforms; } inline const PackUniformHash &uniforms() const { return m_uniforms; } @@ -194,7 +199,7 @@ public: inline QVector<NamedResource> images() const { return m_images; } inline QVector<BlockToUBO> uniformBuffers() const { return m_uniformBuffers; } inline QVector<BlockToSSBO> shaderStorageBuffers() const { return m_shaderStorageBuffers; } - inline QVector<ShaderUniform> submissionUniforms() const { return m_submissionUniforms; } + inline QVector<int> submissionUniformIndices() const { return m_submissionUniformIndices; } private: PackUniformHash m_uniforms; @@ -202,7 +207,7 @@ private: QVector<NamedResource> m_images; QVector<BlockToUBO> m_uniformBuffers; QVector<BlockToSSBO> m_shaderStorageBuffers; - QVector<ShaderUniform> m_submissionUniforms; + QVector<int> m_submissionUniformIndices; friend class RenderView; }; |