summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brasser <mbrasser@ford.com>2019-03-25 13:26:04 -0500
committerMichael Brasser <michael.brasser@live.com>2019-04-01 13:04:36 +0000
commitf0e70c845e2095ff23ecd28f44ca84f6b5349e92 (patch)
treed2c5c8c2906192108c175081b3366627b79ab04a
parente84d8d2a81eb81f9b1ea9f40d4da36d09a97b246 (diff)
Unify shader include handling
Share the code for this between QShaderBuilder and QShaderProgram. As a side effect QShaderProgram gains support for absolute paths. Change-Id: I71dbe0bff702806f0655992008c54bbaa9c4f2c9 Reviewed-by: Paul Lemire <paul.lemire@kdab.com>
-rw-r--r--src/render/materialsystem/qshaderprogram.cpp25
-rw-r--r--src/render/materialsystem/qshaderprogram_p.h3
-rw-r--r--src/render/materialsystem/shaderbuilder.cpp44
-rw-r--r--tests/auto/render/qshaderprogram/included.frag1
-rw-r--r--tests/auto/render/qshaderprogram/main.frag1
-rw-r--r--tests/auto/render/qshaderprogram/mainabsolute.frag1
-rw-r--r--tests/auto/render/qshaderprogram/qshaderprogram.pro3
-rw-r--r--tests/auto/render/qshaderprogram/shaders.qrc7
-rw-r--r--tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp18
9 files changed, 52 insertions, 51 deletions
diff --git a/src/render/materialsystem/qshaderprogram.cpp b/src/render/materialsystem/qshaderprogram.cpp
index 0ca8a9947..c4e14ea2c 100644
--- a/src/render/materialsystem/qshaderprogram.cpp
+++ b/src/render/materialsystem/qshaderprogram.cpp
@@ -635,7 +635,7 @@ QShaderProgram::Status QShaderProgram::status() const
return d->m_status;
}
-static QByteArray deincludify(const QString &filePath)
+QByteArray QShaderProgramPrivate::deincludify(const QString &filePath)
{
QFile f(filePath);
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
@@ -644,20 +644,27 @@ static QByteArray deincludify(const QString &filePath)
}
QByteArray contents = f.readAll();
+ return deincludify(contents, filePath);
+}
+
+QByteArray QShaderProgramPrivate::deincludify(const QByteArray &contents, const QString &filePath)
+{
QByteArrayList lines = contents.split('\n');
const QByteArray includeDirective = QByteArrayLiteral("#pragma include");
for (int i = 0; i < lines.count(); ++i) {
- if (lines[i].startsWith(includeDirective)) {
- QString includeFileName = QFileInfo(filePath).absolutePath()
- + QLatin1Char('/')
- + QString::fromUtf8(lines[i].mid(includeDirective.count() + 1));
+ const auto line = lines[i].simplified();
+ if (line.startsWith(includeDirective)) {
+ const QString includePartialPath = QString::fromUtf8(line.mid(includeDirective.count() + 1));
+
+ QString includePath = QFileInfo(includePartialPath).isAbsolute() ? includePartialPath
+ : QFileInfo(filePath).absolutePath() + QLatin1Char('/') + includePartialPath;
if (qEnvironmentVariableIsSet("QT3D_GLSL100_WORKAROUND")) {
- QString candidate = includeFileName + QLatin1String("100");
+ QString candidate = includePath + QLatin1String("100");
if (QFile::exists(candidate))
- includeFileName = candidate;
+ includePath = candidate;
}
lines.removeAt(i);
- QByteArray includedContents = deincludify(includeFileName);
+ QByteArray includedContents = deincludify(includePath);
lines.insert(i, includedContents);
QString lineDirective = QString(QStringLiteral("#line %1")).arg(i + 2);
lines.insert(i + 1, lineDirective.toUtf8());
@@ -678,7 +685,7 @@ static QByteArray deincludify(const QString &filePath)
QByteArray QShaderProgram::loadSource(const QUrl &sourceUrl)
{
// TO DO: Handle remote path
- return deincludify(Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(sourceUrl));
+ return QShaderProgramPrivate::deincludify(Qt3DRender::QUrlHelper::urlToLocalFileOrQrc(sourceUrl));
}
Qt3DCore::QNodeCreatedChangeBasePtr QShaderProgram::createNodeCreationChange() const
diff --git a/src/render/materialsystem/qshaderprogram_p.h b/src/render/materialsystem/qshaderprogram_p.h
index 92520c3c8..f09b2a30e 100644
--- a/src/render/materialsystem/qshaderprogram_p.h
+++ b/src/render/materialsystem/qshaderprogram_p.h
@@ -75,6 +75,9 @@ public:
void setLog(const QString &log);
void setStatus(QShaderProgram::Status status);
+
+ static QByteArray deincludify(const QByteArray &contents, const QString &filePath);
+ static QByteArray deincludify(const QString &filePath);
};
struct QShaderProgramData
diff --git a/src/render/materialsystem/shaderbuilder.cpp b/src/render/materialsystem/shaderbuilder.cpp
index 283866d68..9c7cb0938 100644
--- a/src/render/materialsystem/shaderbuilder.cpp
+++ b/src/render/materialsystem/shaderbuilder.cpp
@@ -40,6 +40,7 @@
#include "shaderbuilder_p.h"
#include <Qt3DRender/private/qshaderprogrambuilder_p.h>
+#include <Qt3DRender/private/qshaderprogram_p.h>
#include <Qt3DRender/private/qurlhelper_p.h>
#include <QtGui/private/qshaderformat_p.h>
@@ -208,47 +209,6 @@ bool ShaderBuilder::isShaderCodeDirty(ShaderBuilder::ShaderType type) const
return m_dirtyTypes.contains(type);
}
-static QByteArray deincludify(const QByteArray &contents, const QString &filePath);
-
-static QByteArray deincludify(const QString &filePath)
-{
- QFile f(filePath);
- if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
- qWarning() << "Could not read shader source file:" << f.fileName();
- return QByteArray();
- }
-
- QByteArray contents = f.readAll();
- return deincludify(contents, filePath);
-}
-
-static QByteArray deincludify(const QByteArray &contents, const QString &filePath)
-{
- QByteArrayList lines = contents.split('\n');
- const QByteArray includeDirective = QByteArrayLiteral("#pragma include");
- for (int i = 0; i < lines.count(); ++i) {
- const auto line = lines[i].simplified();
- if (line.startsWith(includeDirective)) {
- const QString includePartialPath = QString::fromUtf8(line.mid(includeDirective.count() + 1));
-
- QString includePath = QFileInfo(includePartialPath).isAbsolute() ? includePartialPath
- : QFileInfo(filePath).absolutePath() + QLatin1Char('/') + includePartialPath;
- if (qEnvironmentVariableIsSet("QT3D_GLSL100_WORKAROUND")) {
- QString candidate = includePath + QLatin1String("100");
- if (QFile::exists(candidate))
- includePath = candidate;
- }
- lines.removeAt(i);
- QByteArray includedContents = deincludify(includePath);
- lines.insert(i, includedContents);
- QString lineDirective = QString(QStringLiteral("#line %1")).arg(i + 2);
- lines.insert(i + 1, lineDirective.toUtf8());
- }
- }
-
- return lines.join('\n');
-}
-
void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
{
const auto graphPath = QUrlHelper::urlToLocalFileOrQrc(shaderGraph(type));
@@ -282,7 +242,7 @@ void ShaderBuilder::generateCode(ShaderBuilder::ShaderType type)
generator.graph = graph;
const auto code = generator.createShaderCode(m_enabledLayers);
- m_codes.insert(type, deincludify(code, graphPath + QStringLiteral(".glsl")));
+ m_codes.insert(type, QShaderProgramPrivate::deincludify(code, graphPath + QStringLiteral(".glsl")));
m_dirtyTypes.remove(type);
}
diff --git a/tests/auto/render/qshaderprogram/included.frag b/tests/auto/render/qshaderprogram/included.frag
new file mode 100644
index 000000000..0c954ed15
--- /dev/null
+++ b/tests/auto/render/qshaderprogram/included.frag
@@ -0,0 +1 @@
+out vec4 fragColor;
diff --git a/tests/auto/render/qshaderprogram/main.frag b/tests/auto/render/qshaderprogram/main.frag
new file mode 100644
index 000000000..f30bd8c45
--- /dev/null
+++ b/tests/auto/render/qshaderprogram/main.frag
@@ -0,0 +1 @@
+#pragma include included.frag
diff --git a/tests/auto/render/qshaderprogram/mainabsolute.frag b/tests/auto/render/qshaderprogram/mainabsolute.frag
new file mode 100644
index 000000000..85a013111
--- /dev/null
+++ b/tests/auto/render/qshaderprogram/mainabsolute.frag
@@ -0,0 +1 @@
+#pragma include :/included.frag
diff --git a/tests/auto/render/qshaderprogram/qshaderprogram.pro b/tests/auto/render/qshaderprogram/qshaderprogram.pro
index 6f40caee9..4ab65c455 100644
--- a/tests/auto/render/qshaderprogram/qshaderprogram.pro
+++ b/tests/auto/render/qshaderprogram/qshaderprogram.pro
@@ -8,5 +8,8 @@ CONFIG += testcase
SOURCES += tst_qshaderprogram.cpp
+RESOURCES += \
+ shaders.qrc
+
include(../../core/common/common.pri)
include(../commons/commons.pri)
diff --git a/tests/auto/render/qshaderprogram/shaders.qrc b/tests/auto/render/qshaderprogram/shaders.qrc
new file mode 100644
index 000000000..34a5cd22c
--- /dev/null
+++ b/tests/auto/render/qshaderprogram/shaders.qrc
@@ -0,0 +1,7 @@
+<RCC>
+ <qresource prefix="/">
+ <file>included.frag</file>
+ <file>main.frag</file>
+ <file>mainabsolute.frag</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
index 901ee7349..3fcc49067 100644
--- a/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
+++ b/tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp
@@ -511,6 +511,24 @@ private Q_SLOTS:
QCOMPARE(status(), newStatus);
}
+ void checkIncludes()
+ {
+ // GIVEN
+ Qt3DRender::QShaderProgram shaderProgram;
+ QByteArray includedContent = shaderProgram.loadSource(QUrl(QStringLiteral("qrc:/included.frag")));
+
+ // WHEN (test relative include)
+ QByteArray mainContent = shaderProgram.loadSource(QUrl(QStringLiteral("qrc:/main.frag")));
+
+ // THEN
+ QVERIFY(mainContent.indexOf(includedContent) == 0);
+
+ // WHEN (test absolute include)
+ mainContent = shaderProgram.loadSource(QUrl(QStringLiteral("qrc:/mainabsolute.frag")));
+
+ // THEN
+ QVERIFY(mainContent.indexOf(includedContent) == 0);
+ }
};
QTEST_MAIN(tst_QShaderProgram)