From 1e2902ba3e1285fb2db5a90712135b130fdbbb84 Mon Sep 17 00:00:00 2001 From: Paul Lemire Date: Thu, 26 Nov 2020 09:47:55 +0100 Subject: QShaderProgram: handle binding = auto replacement for raw shader code binding = auto replacement only took place when using shader graphs. This meant providing shader code that used binding = auto or that included snippets that themselves used binding = auto (such as phong.inc.frag) would fail. For that reason, that replacement was moved from the shadergraph builder to QShaderProgramPrivate so that it can be used for both cases: raw shader code or shader graphs. Change-Id: I298a82b83b1181d7a0f19a2e2fefc3aeb9eb81c4 Pick-to: 6.0 6.0.0 Reviewed-by: Mike Krus --- src/render/materialsystem/qshaderprogram.cpp | 69 +++++++++++++++++++++++++++- src/render/materialsystem/qshaderprogram_p.h | 5 ++ src/render/shadergraph/qshadergenerator.cpp | 50 ++------------------ 3 files changed, 78 insertions(+), 46 deletions(-) (limited to 'src/render') diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp index 50eb26a30..1c5eed7f8 100644 --- a/src/render/materialsystem/qshaderprogram.cpp +++ b/src/render/materialsystem/qshaderprogram.cpp @@ -44,6 +44,7 @@ #include #include #include +#include /*! \class Qt3DRender::QShaderProgram @@ -672,6 +673,71 @@ QByteArray QShaderProgramPrivate::deincludify(const QString &filePath) return deincludify(contents, filePath); } +QByteArray QShaderProgramPrivate::resolveAutoBindingIndices(const QByteArray &content, + int ¤tBinding, + int ¤tInputLocation, + int ¤tOutputLocation) +{ + QString shaderCode = QString::fromUtf8(content); + + // This lambda will replace all occurrences of a string (e.g. "binding = auto") by another, + // with the incremented int passed as argument (e.g. "binding = 1", "binding = 2" ...) + const auto replaceAndIncrement = [&](const QRegularExpression ®exp, + int &variable, + const QString &replacement) noexcept { + int matchStart = 0; + do { + matchStart = shaderCode.indexOf(regexp, matchStart); + if (matchStart != -1) { + const auto match = regexp.match(QStringView{shaderCode}.mid(matchStart)); + const auto length = match.capturedLength(0); + + shaderCode.replace(matchStart, length, replacement.arg(variable++)); + } + } while (matchStart != -1); + }; + + // 1. Handle uniforms + { + thread_local const QRegularExpression bindings( + QStringLiteral("binding\\s*=\\s*auto")); + + replaceAndIncrement(bindings, currentBinding, QStringLiteral("binding = %1")); + } + + // 2. Handle inputs + { + thread_local const QRegularExpression inLocations( + QStringLiteral("location\\s*=\\s*auto\\s*\\)\\s*in\\s+")); + + replaceAndIncrement(inLocations, currentInputLocation, + QStringLiteral("location = %1) in ")); + } + + // 3. Handle outputs + { + thread_local const QRegularExpression outLocations( + QStringLiteral("location\\s*=\\s*auto\\s*\\)\\s*out\\s+")); + + replaceAndIncrement(outLocations, currentOutputLocation, + QStringLiteral("location = %1) out ")); + } + + return shaderCode.toUtf8(); +} + +QByteArray QShaderProgramPrivate::resolveAutoBindingIndices(const QByteArray &content) +{ + int currentBinding = 2; // Qt3D default uniforms are 0 and 1 + int currentInputLocation = 0; + int currentOutputLocation = 0; + + return QShaderProgramPrivate::resolveAutoBindingIndices(content, + currentBinding, + currentInputLocation, + currentOutputLocation); +} + QByteArray QShaderProgramPrivate::deincludify(const QByteArray &contents, const QString &filePath) { QByteArrayList lines = contents.split('\n'); @@ -710,7 +776,8 @@ QByteArray QShaderProgramPrivate::deincludify(const QByteArray &contents, const QByteArray QShaderProgram::loadSource(const QUrl &sourceUrl) { // TO DO: Handle remote path - return QShaderProgramPrivate::deincludify(Qt3DCore::QUrlHelper::urlToLocalFileOrQrc(sourceUrl)); + const QByteArray deincluded = QShaderProgramPrivate::deincludify(Qt3DCore::QUrlHelper::urlToLocalFileOrQrc(sourceUrl)); + return QShaderProgramPrivate::resolveAutoBindingIndices(deincluded); } } // of namespace Qt3DRender diff --git a/src/render/materialsystem/qshaderprogram_p.h b/src/render/materialsystem/qshaderprogram_p.h index a3e5b2a3f..0f6d50ed5 100644 --- a/src/render/materialsystem/qshaderprogram_p.h +++ b/src/render/materialsystem/qshaderprogram_p.h @@ -80,6 +80,11 @@ public: static QByteArray deincludify(const QByteArray &contents, const QString &filePath); static QByteArray deincludify(const QString &filePath); + static QByteArray resolveAutoBindingIndices(const QByteArray &content, + int ¤tBinding, + int ¤tInputLocation, + int ¤tOutputLocation); + static QByteArray resolveAutoBindingIndices(const QByteArray &content); }; } // namespace Qt3DRender diff --git a/src/render/shadergraph/qshadergenerator.cpp b/src/render/shadergraph/qshadergenerator.cpp index 3795d3214..9bbc2b2d2 100644 --- a/src/render/shadergraph/qshadergenerator.cpp +++ b/src/render/shadergraph/qshadergenerator.cpp @@ -402,52 +402,12 @@ namespace void onInclude(QByteArrayList &code, const QByteArray &snippet) noexcept { const auto filepath = QString::fromUtf8(snippet.mid(strlen("#pragma include "))); - QString deincluded = QString::fromUtf8(QShaderProgramPrivate::deincludify(filepath)); - - // This lambda will replace all occurrences of a string (e.g. "binding = auto") by another, - // with the incremented int passed as argument (e.g. "binding = 1", "binding = 2" ...) - const auto replaceAndIncrement = [&deincluded](const QRegularExpression ®exp, - int &variable, - const QString &replacement) noexcept { - int matchStart = 0; - do { - matchStart = deincluded.indexOf(regexp, matchStart); - if (matchStart != -1) { - const auto match = regexp.match(QStringView{deincluded}.mid(matchStart)); - const auto length = match.capturedLength(0); - - deincluded.replace(matchStart, length, replacement.arg(variable++)); - } - } while (matchStart != -1); - }; - - // 1. Handle uniforms - { - thread_local const QRegularExpression bindings( - QStringLiteral("binding\\s?+=\\s?+auto")); - - replaceAndIncrement(bindings, currentBinding, QStringLiteral("binding = %1")); - } - - // 2. Handle inputs - { - thread_local const QRegularExpression inLocations( - QStringLiteral("location\\s?+=\\s?+auto\\s?+\\)\\s?+in\\s+")); - - replaceAndIncrement(inLocations, currentInputLocation, - QStringLiteral("location = %1) in ")); - } - - // 3. Handle outputs - { - thread_local const QRegularExpression outLocations( - QStringLiteral("location\\s?+=\\s?+auto\\s?+\\)\\s?+out\\s+")); - - replaceAndIncrement(outLocations, currentOutputLocation, - QStringLiteral("location = %1) out ")); - } + const QByteArray deincluded = QShaderProgramPrivate::deincludify(filepath); - code << deincluded.toUtf8(); + code << QShaderProgramPrivate::resolveAutoBindingIndices(deincluded, + currentBinding, + currentInputLocation, + currentOutputLocation); } int currentInputLocation { 0 }; -- cgit v1.2.3