forked from qt-creator/qt-creator
QmlDesigner: Add shaders pre-compilation support functionality
Task-number: QDS-10499 Change-Id: Idc2722b5b9fea7e2914bae5a67ce289a27c236ae Reviewed-by: Qt CI Patch Build Bot <ci_patchbuild_bot@qt.io> Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
This commit is contained in:
@@ -44,6 +44,21 @@ QStringList CompositionNode::requiredNodes() const
|
|||||||
return m_requiredNodes;
|
return m_requiredNodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CompositionNode::isEnabled() const
|
||||||
|
{
|
||||||
|
return m_isEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompositionNode::setIsEnabled(bool newIsEnabled)
|
||||||
|
{
|
||||||
|
m_isEnabled = newIsEnabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
CompositionNode::NodeType CompositionNode::type() const
|
||||||
|
{
|
||||||
|
return m_type;
|
||||||
|
}
|
||||||
|
|
||||||
void CompositionNode::parse(const QString &qenPath)
|
void CompositionNode::parse(const QString &qenPath)
|
||||||
{
|
{
|
||||||
QFile qenFile(qenPath);
|
QFile qenFile(qenPath);
|
||||||
|
@@ -17,6 +17,12 @@ class CompositionNode : public QObject
|
|||||||
Q_PROPERTY(QObject *nodeUniformsModel READ uniformsModel NOTIFY uniformsModelChanged)
|
Q_PROPERTY(QObject *nodeUniformsModel READ uniformsModel NOTIFY uniformsModelChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
enum NodeType {
|
||||||
|
SourceNode = 0,
|
||||||
|
DestinationNode,
|
||||||
|
CustomNode
|
||||||
|
};
|
||||||
|
|
||||||
CompositionNode(const QString &qenPath);
|
CompositionNode(const QString &qenPath);
|
||||||
|
|
||||||
QString fragmentCode() const;
|
QString fragmentCode() const;
|
||||||
@@ -27,6 +33,11 @@ public:
|
|||||||
|
|
||||||
QStringList requiredNodes() const;
|
QStringList requiredNodes() const;
|
||||||
|
|
||||||
|
NodeType type() const;
|
||||||
|
|
||||||
|
bool isEnabled() const;
|
||||||
|
void setIsEnabled(bool newIsEnabled);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void uniformsModelChanged();
|
void uniformsModelChanged();
|
||||||
|
|
||||||
@@ -34,10 +45,12 @@ private:
|
|||||||
void parse(const QString &qenPath);
|
void parse(const QString &qenPath);
|
||||||
|
|
||||||
QString m_name;
|
QString m_name;
|
||||||
|
NodeType m_type = CustomNode;
|
||||||
QString m_fragmentCode;
|
QString m_fragmentCode;
|
||||||
QString m_vertexCode;
|
QString m_vertexCode;
|
||||||
QString m_description;
|
QString m_description;
|
||||||
QStringList m_requiredNodes;
|
QStringList m_requiredNodes;
|
||||||
|
bool m_isEnabled;
|
||||||
|
|
||||||
EffectMakerUniformsModel m_unifomrsModel;
|
EffectMakerUniformsModel m_unifomrsModel;
|
||||||
};
|
};
|
||||||
|
@@ -112,7 +112,7 @@ const QString EffectMakerModel::getVSUniforms()
|
|||||||
|
|
||||||
const QString EffectMakerModel::getFSUniforms()
|
const QString EffectMakerModel::getFSUniforms()
|
||||||
{
|
{
|
||||||
QList<Uniform *> uniforms = allUniforms();
|
const QList<Uniform *> uniforms = allUniforms();
|
||||||
QString s;
|
QString s;
|
||||||
s += "#version 440\n";
|
s += "#version 440\n";
|
||||||
s += '\n';
|
s += '\n';
|
||||||
@@ -227,4 +227,224 @@ void EffectMakerModel::resetEffectError(int type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QString EffectMakerModel::getDefineProperties()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString EffectMakerModel::getConstVariables()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
int EffectMakerModel::getTagIndex(const QStringList &code, const QString &tag)
|
||||||
|
{
|
||||||
|
Q_UNUSED(code)
|
||||||
|
Q_UNUSED(tag)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::processVertexRootLine(const QString &line)
|
||||||
|
{
|
||||||
|
Q_UNUSED(line)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel:: processFragmentRootLine(const QString &line)
|
||||||
|
{
|
||||||
|
Q_UNUSED(line)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EffectMakerModel::getDefaultRootVertexShader()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EffectMakerModel::getDefaultRootFragmentShader()
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList EffectMakerModel::removeTagsFromCode(const QStringList &codeLines)
|
||||||
|
{
|
||||||
|
Q_UNUSED(codeLines)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::removeTagsFromCode(const QString &code)
|
||||||
|
{
|
||||||
|
Q_UNUSED(code)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::getCustomShaderVaryings(bool outState)
|
||||||
|
{
|
||||||
|
Q_UNUSED(outState)
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::generateVertexShader(bool includeUniforms)
|
||||||
|
{
|
||||||
|
QString s;
|
||||||
|
|
||||||
|
if (includeUniforms)
|
||||||
|
s += getVSUniforms();
|
||||||
|
|
||||||
|
// Remove tags when not generating for features check
|
||||||
|
const bool removeTags = includeUniforms;
|
||||||
|
|
||||||
|
s += getDefineProperties();
|
||||||
|
s += getConstVariables();
|
||||||
|
|
||||||
|
// When the node is complete, add shader code in correct nodes order
|
||||||
|
// split to root and main parts
|
||||||
|
QString s_root;
|
||||||
|
QString s_main;
|
||||||
|
QStringList s_sourceCode;
|
||||||
|
m_shaderVaryingVariables.clear();
|
||||||
|
for (const CompositionNode *n : std::as_const(m_nodes)) {
|
||||||
|
if (!n->vertexCode().isEmpty() && n->isEnabled()) {
|
||||||
|
if (n->type() == CompositionNode::NodeType::SourceNode) {
|
||||||
|
s_sourceCode = n->vertexCode().split('\n');
|
||||||
|
} else if (n->type() == CompositionNode::NodeType::CustomNode) {
|
||||||
|
const QStringList vertexCode = n->vertexCode().split('\n');
|
||||||
|
int mainIndex = getTagIndex(vertexCode, QStringLiteral("main"));
|
||||||
|
int line = 0;
|
||||||
|
for (const QString &ss : vertexCode) {
|
||||||
|
if (mainIndex == -1 || line > mainIndex)
|
||||||
|
s_main += QStringLiteral(" ") + ss + '\n';
|
||||||
|
else if (line < mainIndex)
|
||||||
|
s_root += processVertexRootLine(ss);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_sourceCode.isEmpty()) {
|
||||||
|
// If source nodes doesn't contain any code, use default one
|
||||||
|
s_sourceCode << getDefaultRootVertexShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeTags) {
|
||||||
|
s_sourceCode = removeTagsFromCode(s_sourceCode);
|
||||||
|
s_root = removeTagsFromCode(s_root);
|
||||||
|
s_main = removeTagsFromCode(s_main);
|
||||||
|
}
|
||||||
|
|
||||||
|
s += getCustomShaderVaryings(true);
|
||||||
|
s += s_root + '\n';
|
||||||
|
|
||||||
|
int nodesIndex = getTagIndex(s_sourceCode, QStringLiteral("nodes"));
|
||||||
|
int line = 0;
|
||||||
|
for (const QString &ss : std::as_const(s_sourceCode))
|
||||||
|
s += (line++ == nodesIndex) ? s_main : ss + '\n';
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
QString EffectMakerModel::generateFragmentShader(bool includeUniforms)
|
||||||
|
{
|
||||||
|
QString s;
|
||||||
|
|
||||||
|
if (includeUniforms)
|
||||||
|
s += getFSUniforms();
|
||||||
|
|
||||||
|
// Remove tags when not generating for features check
|
||||||
|
const bool removeTags = includeUniforms;
|
||||||
|
|
||||||
|
s += getDefineProperties();
|
||||||
|
s += getConstVariables();
|
||||||
|
|
||||||
|
// When the node is complete, add shader code in correct nodes order
|
||||||
|
// split to root and main parts
|
||||||
|
QString s_root;
|
||||||
|
QString s_main;
|
||||||
|
QStringList s_sourceCode;
|
||||||
|
for (const CompositionNode *n : std::as_const(m_nodes)) {
|
||||||
|
if (!n->fragmentCode().isEmpty() && n->isEnabled()) {
|
||||||
|
if (n->type() == CompositionNode::NodeType::SourceNode) {
|
||||||
|
s_sourceCode = n->fragmentCode().split('\n');
|
||||||
|
} else if (n->type() == CompositionNode::NodeType::CustomNode) {
|
||||||
|
const QStringList fragmentCode = n->fragmentCode().split('\n');
|
||||||
|
int mainIndex = getTagIndex(fragmentCode, QStringLiteral("main"));
|
||||||
|
int line = 0;
|
||||||
|
for (const QString &ss : fragmentCode) {
|
||||||
|
if (mainIndex == -1 || line > mainIndex)
|
||||||
|
s_main += QStringLiteral(" ") + ss + '\n';
|
||||||
|
else if (line < mainIndex)
|
||||||
|
s_root += processFragmentRootLine(ss);
|
||||||
|
line++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_sourceCode.isEmpty()) {
|
||||||
|
// If source nodes doesn't contain any code, use default one
|
||||||
|
s_sourceCode << getDefaultRootFragmentShader();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (removeTags) {
|
||||||
|
s_sourceCode = removeTagsFromCode(s_sourceCode);
|
||||||
|
s_root = removeTagsFromCode(s_root);
|
||||||
|
s_main = removeTagsFromCode(s_main);
|
||||||
|
}
|
||||||
|
|
||||||
|
s += getCustomShaderVaryings(false);
|
||||||
|
s += s_root + '\n';
|
||||||
|
|
||||||
|
int nodesIndex = getTagIndex(s_sourceCode, QStringLiteral("nodes"));
|
||||||
|
int line = 0;
|
||||||
|
for (const QString &ss : std::as_const(s_sourceCode))
|
||||||
|
s += (line++ == nodesIndex) ? s_main : ss + '\n';
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectMakerModel::bakeShaders()
|
||||||
|
{
|
||||||
|
resetEffectError(ErrorPreprocessor);
|
||||||
|
if (m_vertexShader == generateVertexShader() && m_fragmentShader == generateFragmentShader()) {
|
||||||
|
setShadersUpToDate(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
setShadersUpToDate(false);
|
||||||
|
|
||||||
|
// TODO: Compilation starts here
|
||||||
|
}
|
||||||
|
|
||||||
|
bool EffectMakerModel::shadersUpToDate() const
|
||||||
|
{
|
||||||
|
return m_shadersUpToDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void EffectMakerModel::setShadersUpToDate(bool UpToDate)
|
||||||
|
{
|
||||||
|
if (m_shadersUpToDate == UpToDate)
|
||||||
|
return;
|
||||||
|
m_shadersUpToDate = UpToDate;
|
||||||
|
emit shadersUpToDateChanged();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
@@ -18,6 +18,7 @@ struct EffectError {
|
|||||||
Q_PROPERTY(QString message MEMBER m_message)
|
Q_PROPERTY(QString message MEMBER m_message)
|
||||||
Q_PROPERTY(int line MEMBER m_line)
|
Q_PROPERTY(int line MEMBER m_line)
|
||||||
Q_PROPERTY(int type MEMBER m_type)
|
Q_PROPERTY(int type MEMBER m_type)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
QString m_message;
|
QString m_message;
|
||||||
int m_line = -1;
|
int m_line = -1;
|
||||||
@@ -30,6 +31,7 @@ class EffectMakerModel : public QAbstractListModel
|
|||||||
|
|
||||||
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
|
Q_PROPERTY(bool isEmpty MEMBER m_isEmpty NOTIFY isEmptyChanged)
|
||||||
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
|
Q_PROPERTY(int selectedIndex MEMBER m_selectedIndex NOTIFY selectedIndexChanged)
|
||||||
|
Q_PROPERTY(bool shadersUpToDate READ shadersUpToDate WRITE setShadersUpToDate NOTIFY shadersUpToDateChanged)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
EffectMakerModel(QObject *parent = nullptr);
|
EffectMakerModel(QObject *parent = nullptr);
|
||||||
@@ -44,10 +46,14 @@ public:
|
|||||||
|
|
||||||
Q_INVOKABLE void removeNode(int idx);
|
Q_INVOKABLE void removeNode(int idx);
|
||||||
|
|
||||||
|
bool shadersUpToDate() const;
|
||||||
|
void setShadersUpToDate(bool newShadersUpToDate);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void isEmptyChanged();
|
void isEmptyChanged();
|
||||||
void selectedIndexChanged(int idx);
|
void selectedIndexChanged(int idx);
|
||||||
void effectErrorChanged();
|
void effectErrorChanged();
|
||||||
|
void shadersUpToDateChanged();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Roles {
|
enum Roles {
|
||||||
@@ -55,6 +61,15 @@ private:
|
|||||||
UniformsRole
|
UniformsRole
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum ErrorTypes {
|
||||||
|
ErrorCommon = -1,
|
||||||
|
ErrorQMLParsing,
|
||||||
|
ErrorVert,
|
||||||
|
ErrorFrag,
|
||||||
|
ErrorQMLRuntime,
|
||||||
|
ErrorPreprocessor
|
||||||
|
};
|
||||||
|
|
||||||
bool isValidIndex(int idx) const;
|
bool isValidIndex(int idx) const;
|
||||||
|
|
||||||
const QList<Uniform *> allUniforms();
|
const QList<Uniform *> allUniforms();
|
||||||
@@ -68,14 +83,31 @@ private:
|
|||||||
void setEffectError(const QString &errorMessage, int type, int lineNumber);
|
void setEffectError(const QString &errorMessage, int type, int lineNumber);
|
||||||
void resetEffectError(int type);
|
void resetEffectError(int type);
|
||||||
|
|
||||||
|
const QString getDefineProperties();
|
||||||
|
const QString getConstVariables();
|
||||||
|
int getTagIndex(const QStringList &code, const QString &tag);
|
||||||
|
QString processVertexRootLine(const QString &line);
|
||||||
|
QString processFragmentRootLine(const QString &line);
|
||||||
|
QStringList getDefaultRootVertexShader();
|
||||||
|
QStringList getDefaultRootFragmentShader();
|
||||||
|
QStringList removeTagsFromCode(const QStringList &codeLines);
|
||||||
|
QString removeTagsFromCode(const QString &code);
|
||||||
|
QString getCustomShaderVaryings(bool outState);
|
||||||
|
QString generateVertexShader(bool includeUniforms = true);
|
||||||
|
QString generateFragmentShader(bool includeUniforms = true);
|
||||||
|
void bakeShaders();
|
||||||
|
|
||||||
QList<CompositionNode *> m_nodes;
|
QList<CompositionNode *> m_nodes;
|
||||||
|
|
||||||
int m_selectedIndex = -1;
|
int m_selectedIndex = -1;
|
||||||
bool m_isEmpty = true;
|
bool m_isEmpty = true;
|
||||||
|
// True when shaders haven't changed since last baking
|
||||||
|
bool m_shadersUpToDate = true;
|
||||||
QMap<int, EffectError> m_effectErrors;
|
QMap<int, EffectError> m_effectErrors;
|
||||||
|
|
||||||
ShaderFeatures m_shaderFeatures;
|
ShaderFeatures m_shaderFeatures;
|
||||||
|
QStringList m_shaderVaryingVariables;
|
||||||
|
QString m_fragmentShader;
|
||||||
|
QString m_vertexShader;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace QmlDesigner
|
} // namespace QmlDesigner
|
||||||
|
Reference in New Issue
Block a user