summaryrefslogtreecommitdiffstats
path: root/src/render
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2020-11-26 09:47:55 +0100
committerPaul Lemire <paul.lemire@kdab.com>2020-11-26 16:42:00 +0100
commit1e2902ba3e1285fb2db5a90712135b130fdbbb84 (patch)
tree9c978b0ea1bca417485ca96ddb805cebbe6af423 /src/render
parentd6b548ac820502b961f577993cefb1b7bdd24a43 (diff)
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 <mike.krus@kdab.com>
Diffstat (limited to 'src/render')
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp69
-rw-r--r--src/render/materialsystem/qshaderprogram_p.h5
-rw-r--r--src/render/shadergraph/qshadergenerator.cpp50
3 files changed, 78 insertions, 46 deletions
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 <QFile>
#include <QFileInfo>
#include <QUrl>
+#include <QRegularExpression>
/*!
\class Qt3DRender::QShaderProgram
@@ -672,6 +673,71 @@ QByteArray QShaderProgramPrivate::deincludify(const QString &filePath)
return deincludify(contents, filePath);
}
+QByteArray QShaderProgramPrivate::resolveAutoBindingIndices(const QByteArray &content,
+ int &currentBinding,
+ int &currentInputLocation,
+ int &currentOutputLocation)
+{
+ 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 &regexp,
+ 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 &currentBinding,
+ int &currentInputLocation,
+ int &currentOutputLocation);
+ 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 &regexp,
- 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 };