diff options
Diffstat (limited to 'src/plugins/renderers/opengl/renderer/commandexecuter.cpp')
-rw-r--r-- | src/plugins/renderers/opengl/renderer/commandexecuter.cpp | 391 |
1 files changed, 391 insertions, 0 deletions
diff --git a/src/plugins/renderers/opengl/renderer/commandexecuter.cpp b/src/plugins/renderers/opengl/renderer/commandexecuter.cpp new file mode 100644 index 000000000..03d5d5a7f --- /dev/null +++ b/src/plugins/renderers/opengl/renderer/commandexecuter.cpp @@ -0,0 +1,391 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Paul Lemire <paul.lemire350@gmail.com> +** Contact: http://www.qt-project.org/legal +** +** This file is part of the Qt3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 http://www.qt.io/terms-conditions. For further +** information use the contact form at http://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.LGPLv3 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.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 later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "commandexecuter_p.h" + +#include <Qt3DCore/private/qabstractaspect_p.h> +#include <Qt3DCore/qbackendnode.h> +#include <Qt3DRender/private/nodemanagers_p.h> +#include <Qt3DRender/private/geometryrenderermanager_p.h> +#include <Qt3DRender/private/stringtoint_p.h> +#include <QJsonObject> +#include <QJsonDocument> +#include <QJsonArray> +#include <graphicscontext_p.h> +#include <renderview_p.h> +#include <rendercommand_p.h> +#include <renderer_p.h> +#include <submissioncontext_p.h> + +QT_BEGIN_NAMESPACE + +namespace Qt3DRender { + +namespace Debug { + +namespace { + +template<typename Type> +QJsonObject typeToJsonObj(const Type &) +{ + return QJsonObject(); +} + +template<typename Type> +QJsonValue typeToJsonValue(const Type &t) +{ + Q_UNUSED(t); + return QJsonValue(); +} + +template<> +QJsonObject typeToJsonObj<QRectF>(const QRectF &rect) +{ + QJsonObject obj; + + obj.insert(QLatin1String("x"), rect.x()); + obj.insert(QLatin1String("y"), rect.y()); + obj.insert(QLatin1String("width"), rect.width()); + obj.insert(QLatin1String("height"), rect.height()); + + return obj; +} + +template<> +QJsonValue typeToJsonValue<QRectF>(const QRectF &rect) +{ + QJsonArray value; + + value.push_back(rect.x()); + value.push_back(rect.y()); + value.push_back(rect.width()); + value.push_back(rect.height()); + + return value; +} + +template<> +QJsonObject typeToJsonObj<QSize>(const QSize &s) +{ + QJsonObject obj; + + obj.insert(QLatin1String("width"), s.width()); + obj.insert(QLatin1String("height"), s.height()); + + return obj; +} + +template<> +QJsonValue typeToJsonValue<QSize>(const QSize &s) +{ + QJsonArray value; + + value.push_back(s.width()); + value.push_back(s.height()); + + return value; +} + +template<> +QJsonObject typeToJsonObj<QVector3D>(const QVector3D &v) +{ + QJsonObject obj; + + obj.insert(QLatin1String("x"), v.x()); + obj.insert(QLatin1String("y"), v.y()); + obj.insert(QLatin1String("z"), v.z()); + + return obj; +} + +template<> +QJsonValue typeToJsonValue<QVector3D>(const QVector3D &v) +{ + QJsonArray value; + + value.push_back(v.x()); + value.push_back(v.y()); + value.push_back(v.z()); + + return value; +} + +template<> +QJsonObject typeToJsonObj<Qt3DCore::QNodeId>(const Qt3DCore::QNodeId &v) +{ + QJsonObject obj; + obj.insert(QLatin1String("id"), qint64(v.id())); + return obj; +} + +template<> +QJsonValue typeToJsonValue<Qt3DCore::QNodeId>(const Qt3DCore::QNodeId &v) +{ + QJsonValue value(qint64(v.id())); + return value; +} + +template<> +QJsonObject typeToJsonObj<QVector4D>(const QVector4D &v) +{ + QJsonObject obj; + + obj.insert(QLatin1String("x"), v.x()); + obj.insert(QLatin1String("y"), v.y()); + obj.insert(QLatin1String("z"), v.z()); + obj.insert(QLatin1String("w"), v.w()); + + return obj; +} + +template<> +QJsonValue typeToJsonValue<QVector4D>(const QVector4D &v) +{ + QJsonArray value; + + value.push_back(v.x()); + value.push_back(v.y()); + value.push_back(v.z()); + value.push_back(v.w()); + + return value; +} + +template<> +QJsonObject typeToJsonObj<QMatrix4x4>(const QMatrix4x4 &v) +{ + QJsonObject obj; + + obj.insert(QLatin1String("row 0"), typeToJsonObj(v.row(0))); + obj.insert(QLatin1String("row 1"), typeToJsonObj(v.row(0))); + obj.insert(QLatin1String("row 2"), typeToJsonObj(v.row(0))); + obj.insert(QLatin1String("row 3"), typeToJsonObj(v.row(0))); + + return obj; +} + +template<> +QJsonValue typeToJsonValue<QMatrix4x4>(const QMatrix4x4 &v) +{ + QJsonArray value; + + value.push_back(typeToJsonValue(v.row(0))); + value.push_back(typeToJsonValue(v.row(1))); + value.push_back(typeToJsonValue(v.row(2))); + value.push_back(typeToJsonValue(v.row(3))); + + return value; +} + +template<> +QJsonValue typeToJsonValue<QVariant>(const QVariant &v) +{ + const int nodeTypeId = qMetaTypeId<Qt3DCore::QNodeId>(); + + if (v.userType() == nodeTypeId) + return typeToJsonValue(v.value<Qt3DCore::QNodeId>()); + + switch (v.userType()) { + case QMetaType::QVector3D: + return typeToJsonValue(v.value<QVector3D>()); + case QMetaType::QVector4D: + return typeToJsonValue(v.value<QVector4D>()); + case QMetaType::QMatrix4x4: + return typeToJsonValue(v.value<QMatrix4x4>()); + default: + return QJsonValue::fromVariant(v); + } +} + +template<typename Handle, typename Manager> +QJsonObject backendNodeToJSon(Handle handle, Manager *manager) +{ + Qt3DCore::QBackendNode *node = manager->data(handle); + QJsonObject obj; + Qt3DCore::QNodeId id; + if (node != nullptr) + id = node->peerId(); + obj.insert(QLatin1String("id"), qint64(id.id())); + return obj; +} + +QJsonObject parameterPackToJson(const Render::OpenGL::ShaderParameterPack &pack) +{ + QJsonObject obj; + + const Render::OpenGL::PackUniformHash &uniforms = pack.uniforms(); + QJsonArray uniformsArray; + for (int i = 0, m = uniforms.keys.size(); i < m; ++i) { + QJsonObject uniformObj; + uniformObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(uniforms.keys.at(i))); + const Render::UniformValue::ValueType type = uniforms.values.at(i).valueType(); + uniformObj.insert(QLatin1String("type"), + type == Render::UniformValue::ScalarValue + ? QLatin1String("value") + : QLatin1String("texture")); + uniformsArray.push_back(uniformObj); + } + obj.insert(QLatin1String("uniforms"), uniformsArray); + + QJsonArray texturesArray; + const QVector<Render::OpenGL::ShaderParameterPack::NamedResource> &textures = pack.textures(); + for (const auto & texture : textures) { + QJsonObject textureObj; + textureObj.insert(QLatin1String("name"), Render::StringToInt::lookupString(texture.glslNameId)); + textureObj.insert(QLatin1String("id"), qint64(texture.nodeId.id())); + texturesArray.push_back(textureObj); + } + obj.insert(QLatin1String("textures"), texturesArray); + + const QVector<Render::OpenGL::BlockToUBO> &ubos = pack.uniformBuffers(); + QJsonArray ubosArray; + for (const auto &ubo : ubos) { + QJsonObject uboObj; + uboObj.insert(QLatin1String("index"), ubo.m_blockIndex); + uboObj.insert(QLatin1String("bufferId"), qint64(ubo.m_bufferID.id())); + ubosArray.push_back(uboObj); + + } + obj.insert(QLatin1String("ubos"), ubosArray); + + const QVector<Render::OpenGL::BlockToSSBO> &ssbos = pack.shaderStorageBuffers(); + QJsonArray ssbosArray; + for (const auto &ssbo : ssbos) { + QJsonObject ssboObj; + ssboObj.insert(QLatin1String("index"), ssbo.m_blockIndex); + ssboObj.insert(QLatin1String("bufferId"), qint64(ssbo.m_bufferID.id())); + ssbosArray.push_back(ssboObj); + } + obj.insert(QLatin1String("ssbos"), ssbosArray); + + return obj; +} + +} // anonymous + +CommandExecuter::CommandExecuter(Render::OpenGL::Renderer *renderer) + : m_renderer(renderer) +{ +} + +// Render thread +void CommandExecuter::performAsynchronousCommandExecution(const QVector<Render::OpenGL::RenderView *> &views) +{ + QMutexLocker lock(&m_pendingCommandsMutex); + const QVector<Qt3DCore::Debug::AsynchronousCommandReply *> shellCommands = std::move(m_pendingCommands); + lock.unlock(); + + for (auto *reply : shellCommands) { + if (reply->commandName() == QLatin1String("glinfo")) { + QJsonObject replyObj; + const GraphicsApiFilterData *contextInfo = m_renderer->submissionContext()->contextInfo(); + if (contextInfo != nullptr) { + replyObj.insert(QLatin1String("api"), + contextInfo->m_api == QGraphicsApiFilter::OpenGL + ? QLatin1String("OpenGL") + : QLatin1String("OpenGLES")); + const QString versionString = + QString::number(contextInfo->m_major) + + QStringLiteral(".") + + QString::number(contextInfo->m_minor); + replyObj.insert(QLatin1String("version"), versionString); + replyObj.insert(QLatin1String("profile"), + contextInfo->m_profile == QGraphicsApiFilter::CoreProfile + ? QLatin1String("Core") + : contextInfo->m_profile == QGraphicsApiFilter::CompatibilityProfile + ? QLatin1String("Compatibility") + : QLatin1String("None")); + } + reply->setData(QJsonDocument(replyObj).toJson()); + } else if (reply->commandName() == QLatin1String("rendercommands")) { + QJsonObject replyObj; + + QJsonArray viewArray; + for (Render::OpenGL::RenderView *v : views) { + QJsonObject viewObj; + viewObj.insert(QLatin1String("viewport"), typeToJsonValue(v->viewport())); + viewObj.insert(QLatin1String("surfaceSize"), typeToJsonValue(v->surfaceSize())); + viewObj.insert(QLatin1String("devicePixelRatio"), v->devicePixelRatio()); + viewObj.insert(QLatin1String("noDraw"), v->noDraw()); + viewObj.insert(QLatin1String("frustumCulling"), v->frustumCulling()); + viewObj.insert(QLatin1String("compute"), v->isCompute()); + viewObj.insert(QLatin1String("clearDepthValue"), v->clearDepthValue()); + viewObj.insert(QLatin1String("clearStencilValue"), v->clearStencilValue()); + + QJsonArray renderCommandsArray; + for (Render::OpenGL::RenderCommand &c : v->commands()) { + QJsonObject commandObj; + Render::NodeManagers *nodeManagers = m_renderer->nodeManagers(); + commandObj.insert(QLatin1String("shader"), typeToJsonValue(QVariant::fromValue(c.m_shaderId))); + commandObj.insert(QLatin1String("vao"), double(c.m_vao.handle())); + commandObj.insert(QLatin1String("instanceCount"), c.m_instanceCount); + commandObj.insert(QLatin1String("geometry"), backendNodeToJSon(c.m_geometry, nodeManagers->geometryManager())); + commandObj.insert(QLatin1String("geometryRenderer"), backendNodeToJSon(c.m_geometryRenderer, nodeManagers->geometryRendererManager())); + commandObj.insert(QLatin1String("shaderParameterPack"), parameterPackToJson(c.m_parameterPack)); + + renderCommandsArray.push_back(commandObj); + } + viewObj.insert(QLatin1String("commands"), renderCommandsArray); + viewArray.push_back(viewObj); + } + + replyObj.insert(QLatin1String("renderViews"), viewArray); + reply->setData(QJsonDocument(replyObj).toJson()); + } + reply->setFinished(true); + } +} + +// Main thread +QVariant CommandExecuter::executeCommand(const QStringList &args) +{ + // Note: The replies will be deleted by the AspectCommandDebugger + if (args.length() > 0 && + (args.first() == QLatin1String("glinfo") || + args.first() == QLatin1String("rendercommands"))) { + auto reply = new Qt3DCore::Debug::AsynchronousCommandReply(args.first()); + QMutexLocker lock(&m_pendingCommandsMutex); + m_pendingCommands.push_back(reply); + return QVariant::fromValue(reply); + } + return QVariant(); +} + +} // Debug + +} // Qt3DRenderer + +QT_END_NAMESPACE |