diff options
author | Michael Brasser <mbrasser@ford.com> | 2019-03-25 13:26:04 -0500 |
---|---|---|
committer | Michael Brasser <michael.brasser@live.com> | 2019-04-01 13:04:36 +0000 |
commit | f0e70c845e2095ff23ecd28f44ca84f6b5349e92 (patch) | |
tree | d2c5c8c2906192108c175081b3366627b79ab04a | |
parent | e84d8d2a81eb81f9b1ea9f40d4da36d09a97b246 (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.cpp | 25 | ||||
-rw-r--r-- | src/render/materialsystem/qshaderprogram_p.h | 3 | ||||
-rw-r--r-- | src/render/materialsystem/shaderbuilder.cpp | 44 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/included.frag | 1 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/main.frag | 1 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/mainabsolute.frag | 1 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/qshaderprogram.pro | 3 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/shaders.qrc | 7 | ||||
-rw-r--r-- | tests/auto/render/qshaderprogram/tst_qshaderprogram.cpp | 18 |
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) |