forked from qt-creator/qt-creator
QmlDesigner: Add more shader compiling support functionality
Functionality for adding default shaders, tags, and varying variables Task-number: QDS-10499 Change-Id: Ib32e558510fb37c29765d2467cfc4c047a446a87 Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -4,8 +4,10 @@
|
|||||||
#include "effectmakermodel.h"
|
#include "effectmakermodel.h"
|
||||||
|
|
||||||
#include "compositionnode.h"
|
#include "compositionnode.h"
|
||||||
|
#include "syntaxhighlighterdata.h"
|
||||||
#include "uniform.h"
|
#include "uniform.h"
|
||||||
|
|
||||||
|
#include <QByteArrayView>
|
||||||
#include <QRegularExpression>
|
#include <QRegularExpression>
|
||||||
#include <QVector2D>
|
#include <QVector2D>
|
||||||
|
|
||||||
@@ -166,7 +168,6 @@ const QString EffectMakerModel::getFSUniforms()
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Detects common GLSL error messages and returns potential
|
// Detects common GLSL error messages and returns potential
|
||||||
// additional error information related to them.
|
// additional error information related to them.
|
||||||
QString EffectMakerModel::detectErrorMessage(const QString &errorMessage)
|
QString EffectMakerModel::detectErrorMessage(const QString &errorMessage)
|
||||||
@@ -210,8 +211,7 @@ void EffectMakerModel::setEffectError(const QString &errorMessage, int type, int
|
|||||||
// For shaders, get the line number from baker output.
|
// For shaders, get the line number from baker output.
|
||||||
// Which is something like "ERROR: :15: message"
|
// Which is something like "ERROR: :15: message"
|
||||||
int glslErrorLineNumber = -1;
|
int glslErrorLineNumber = -1;
|
||||||
static QRegularExpression spaceReg("\\s+");
|
QStringList errorStringList = errorMessage.split(m_spaceReg, Qt::SkipEmptyParts);
|
||||||
QStringList errorStringList = errorMessage.split(spaceReg, Qt::SkipEmptyParts);
|
|
||||||
if (errorStringList.size() >= 2) {
|
if (errorStringList.size() >= 2) {
|
||||||
QString lineString = errorStringList.at(1).trimmed();
|
QString lineString = errorStringList.at(1).trimmed();
|
||||||
if (lineString.size() >= 3) {
|
if (lineString.size() >= 3) {
|
||||||
@@ -284,69 +284,137 @@ const QString EffectMakerModel::getConstVariables()
|
|||||||
|
|
||||||
const QString EffectMakerModel::getDefineProperties()
|
const QString EffectMakerModel::getDefineProperties()
|
||||||
{
|
{
|
||||||
// TODO
|
const QList<Uniform *> uniforms = allUniforms();
|
||||||
return QString();
|
QString s;
|
||||||
|
for (Uniform *uniform : uniforms) {
|
||||||
|
// TODO: Check if uniform is already added.
|
||||||
|
if (uniform->type() == Uniform::Type::Define) {
|
||||||
|
QString defineValue = uniform->value().toString();
|
||||||
|
s += QString("#define %1 %2\n").arg(uniform->name(), defineValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!s.isEmpty())
|
||||||
|
s += '\n';
|
||||||
|
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
int EffectMakerModel::getTagIndex(const QStringList &code, const QString &tag)
|
int EffectMakerModel::getTagIndex(const QStringList &code, const QString &tag)
|
||||||
{
|
{
|
||||||
Q_UNUSED(code)
|
int index = -1;
|
||||||
Q_UNUSED(tag)
|
int line = 0;
|
||||||
|
const QString tagString = QString("@%1").arg(tag);
|
||||||
// TODO
|
for (const QString &s : code) {
|
||||||
return 0;
|
auto st = s.trimmed();
|
||||||
|
// Check if line or first non-space content of the line matches to tag
|
||||||
|
static auto spaceReg = QRegularExpression("\\s");
|
||||||
|
auto firstSpace = st.indexOf(spaceReg);
|
||||||
|
QString firstWord = st;
|
||||||
|
if (firstSpace > 0)
|
||||||
|
firstWord = st.sliced(0, firstSpace);
|
||||||
|
if (firstWord == tagString) {
|
||||||
|
index = line;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EffectMakerModel::processVertexRootLine(const QString &line)
|
QString EffectMakerModel::processVertexRootLine(const QString &line)
|
||||||
{
|
{
|
||||||
Q_UNUSED(line)
|
QString output;
|
||||||
|
QStringList lineList = line.split(m_spaceReg, Qt::SkipEmptyParts);
|
||||||
// TODO
|
if (lineList.length() > 1 && lineList.at(0) == QStringLiteral("out")) {
|
||||||
return QString();
|
lineList.removeFirst();
|
||||||
|
QString outLine = lineList.join(' ');
|
||||||
|
m_shaderVaryingVariables << outLine;
|
||||||
|
} else {
|
||||||
|
output = line + '\n';
|
||||||
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EffectMakerModel:: processFragmentRootLine(const QString &line)
|
QString EffectMakerModel::processFragmentRootLine(const QString &line)
|
||||||
{
|
{
|
||||||
Q_UNUSED(line)
|
QString output;
|
||||||
|
QStringList lineList = line.split(m_spaceReg, Qt::SkipEmptyParts);
|
||||||
// TODO
|
// Just skip all "in" variables. It is enough to have "out" variable in vertex.
|
||||||
return QString();
|
if (lineList.length() > 1 && lineList.at(0) == QStringLiteral("in"))
|
||||||
|
return QString();
|
||||||
|
output = line + '\n';
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList EffectMakerModel::getDefaultRootVertexShader()
|
QStringList EffectMakerModel::getDefaultRootVertexShader()
|
||||||
{
|
{
|
||||||
// TODO
|
if (m_defaultRootVertexShader.isEmpty()) {
|
||||||
return {};
|
m_defaultRootVertexShader << "void main() {";
|
||||||
|
m_defaultRootVertexShader << " texCoord = qt_MultiTexCoord0;";
|
||||||
|
m_defaultRootVertexShader << " fragCoord = qt_Vertex.xy;";
|
||||||
|
m_defaultRootVertexShader << " vec2 vertCoord = qt_Vertex.xy;";
|
||||||
|
m_defaultRootVertexShader << " @nodes";
|
||||||
|
m_defaultRootVertexShader << " gl_Position = qt_Matrix * vec4(vertCoord, 0.0, 1.0);";
|
||||||
|
m_defaultRootVertexShader << "}";
|
||||||
|
}
|
||||||
|
return m_defaultRootVertexShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
QStringList EffectMakerModel::getDefaultRootFragmentShader()
|
QStringList EffectMakerModel::getDefaultRootFragmentShader()
|
||||||
{
|
{
|
||||||
// TODO
|
if (m_defaultRootFragmentShader.isEmpty()) {
|
||||||
return {};
|
m_defaultRootFragmentShader << "void main() {";
|
||||||
|
m_defaultRootFragmentShader << " fragColor = texture(iSource, texCoord);";
|
||||||
|
m_defaultRootFragmentShader << " @nodes";
|
||||||
|
m_defaultRootFragmentShader << " fragColor = fragColor * qt_Opacity;";
|
||||||
|
m_defaultRootFragmentShader << "}";
|
||||||
|
}
|
||||||
|
return m_defaultRootFragmentShader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all post-processing tags ("@tag") from the code.
|
||||||
|
// Except "@nodes" tag as that is handled later.
|
||||||
QStringList EffectMakerModel::removeTagsFromCode(const QStringList &codeLines)
|
QStringList EffectMakerModel::removeTagsFromCode(const QStringList &codeLines)
|
||||||
{
|
{
|
||||||
Q_UNUSED(codeLines)
|
QStringList s;
|
||||||
|
for (const QString &line : codeLines) {
|
||||||
// TODO
|
const auto trimmedLine = line.trimmed();
|
||||||
return {};
|
if (!trimmedLine.startsWith('@') || trimmedLine.startsWith("@nodes")) {
|
||||||
|
s << line;
|
||||||
|
} else {
|
||||||
|
// Check if the tag is known
|
||||||
|
bool validTag = false;
|
||||||
|
const QList<QByteArrayView> tags = SyntaxHighlighterData::reservedTagNames();
|
||||||
|
QString firstWord = trimmedLine.split(m_spaceReg, Qt::SkipEmptyParts).first();
|
||||||
|
for (const QByteArrayView &tag : tags) {
|
||||||
|
if (firstWord == QString::fromUtf8(tag)) {
|
||||||
|
validTag = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!validTag)
|
||||||
|
setEffectError(QString("Unknown tag: %1").arg(trimmedLine), ErrorPreprocessor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EffectMakerModel::removeTagsFromCode(const QString &code)
|
QString EffectMakerModel::removeTagsFromCode(const QString &code)
|
||||||
{
|
{
|
||||||
Q_UNUSED(code)
|
QStringList codeLines = removeTagsFromCode(code.split('\n'));
|
||||||
|
return codeLines.join('\n');
|
||||||
// TODO
|
|
||||||
return QString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EffectMakerModel::getCustomShaderVaryings(bool outState)
|
QString EffectMakerModel::getCustomShaderVaryings(bool outState)
|
||||||
{
|
{
|
||||||
Q_UNUSED(outState)
|
QString output;
|
||||||
|
QString direction = outState ? QStringLiteral("out") : QStringLiteral("in");
|
||||||
// TODO
|
int varLocation = m_shaderFeatures.enabled(ShaderFeatures::FragCoord) ? 2 : 1;
|
||||||
return QString();
|
for (const QString &var : std::as_const(m_shaderVaryingVariables)) {
|
||||||
|
output += QString("layout(location = %1) %2 %3\n").arg(QString::number(varLocation), direction, var);
|
||||||
|
varLocation++;
|
||||||
|
}
|
||||||
|
return output;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString EffectMakerModel::generateVertexShader(bool includeUniforms)
|
QString EffectMakerModel::generateVertexShader(bool includeUniforms)
|
||||||
|
@@ -110,6 +110,10 @@ private:
|
|||||||
QStringList m_shaderVaryingVariables;
|
QStringList m_shaderVaryingVariables;
|
||||||
QString m_fragmentShader;
|
QString m_fragmentShader;
|
||||||
QString m_vertexShader;
|
QString m_vertexShader;
|
||||||
|
QStringList m_defaultRootVertexShader;
|
||||||
|
QStringList m_defaultRootFragmentShader;
|
||||||
|
|
||||||
|
const QRegularExpression m_spaceReg = QRegularExpression("\\s+");
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
Reference in New Issue
Block a user