diff --git a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp index 8016e13d7..05de3850e 100644 --- a/include/Nazara/Shader/Ast/SanitizeVisitor.hpp +++ b/include/Nazara/Shader/Ast/SanitizeVisitor.hpp @@ -10,6 +10,7 @@ #include #include #include +#include #include namespace Nz::ShaderAst @@ -32,6 +33,7 @@ namespace Nz::ShaderAst struct Options { + std::unordered_set reservedIdentifiers; bool removeOptionDeclaration = true; }; @@ -84,6 +86,8 @@ namespace Nz::ShaderAst std::size_t ResolveStruct(const UniformType& uniformType); ExpressionType ResolveType(const ExpressionType& exprType); + void SanitizeIdentifier(std::string& identifier); + struct Alias { std::variant value; diff --git a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp index 3698a0485..09bdd3db4 100644 --- a/src/Nazara/Shader/Ast/SanitizeVisitor.cpp +++ b/src/Nazara/Shader/Ast/SanitizeVisitor.cpp @@ -587,6 +587,8 @@ namespace Nz::ShaderAst auto clone = static_unique_pointer_cast(AstCloner::Clone(node)); for (auto& extVar : clone->externalVars) { + SanitizeIdentifier(extVar.name); + extVar.type = ResolveType(extVar.type); ExpressionType varType; @@ -628,6 +630,8 @@ namespace Nz::ShaderAst clone->parameters = node.parameters; clone->returnType = ResolveType(node.returnType); + SanitizeIdentifier(clone->name); + PushScope(); { for (auto& parameter : clone->parameters) @@ -636,6 +640,8 @@ namespace Nz::ShaderAst std::size_t varIndex = RegisterVariable(parameter.name, parameter.type); if (!clone->varIndex) clone->varIndex = varIndex; //< First parameter variable index is node variable index + + SanitizeIdentifier(parameter.name); } clone->statements.reserve(node.statements.size()); @@ -696,6 +702,8 @@ namespace Nz::ShaderAst clone->structIndex = RegisterStruct(clone->description.name, clone->description); + SanitizeIdentifier(clone->description.name); + return clone; } @@ -714,6 +722,8 @@ namespace Nz::ShaderAst clone->varIndex = RegisterVariable(clone->varName, clone->varType); + SanitizeIdentifier(clone->varName); + return clone; } @@ -858,6 +868,19 @@ namespace Nz::ShaderAst }, exprType); } + void SanitizeVisitor::SanitizeIdentifier(std::string& identifier) + { + // Append _ until the identifier is no longer found + while (m_context->options.reservedIdentifiers.find(identifier) != m_context->options.reservedIdentifiers.end()) + { + do + { + identifier += "_"; + } + while (FindIdentifier(identifier) != nullptr); + } + } + void SanitizeVisitor::TypeMustMatch(ExpressionPtr& left, ExpressionPtr& right) { return TypeMustMatch(GetExpressionType(*left), GetExpressionType(*right)); diff --git a/src/Nazara/Shader/GlslWriter.cpp b/src/Nazara/Shader/GlslWriter.cpp index 52be29494..006f830a9 100644 --- a/src/Nazara/Shader/GlslWriter.cpp +++ b/src/Nazara/Shader/GlslWriter.cpp @@ -113,7 +113,13 @@ namespace Nz m_currentState = nullptr; }); - ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader); + ShaderAst::SanitizeVisitor::Options options; + options.reservedIdentifiers = { + // All reserved GLSL keywords as of GLSL ES 3.2 + "active", "asm", "atomic_uint", "attribute", "bool", "break", "buffer", "bvec2", "bvec3", "bvec4", "case", "cast", "centroid", "class", "coherent", "common", "const", "continue", "default", "discard", "dmat2", "dmat2x2", "dmat2x3", "dmat2x4", "dmat3", "dmat3x2", "dmat3x3", "dmat3x4", "dmat4", "dmat4x2", "dmat4x3", "dmat4x4", "do", "double", "dvec2", "dvec3", "dvec4", "else", "enum", "extern", "external", "false", "filter", "fixed", "flat", "float", "for", "fvec2", "fvec3", "fvec4", "goto", "half", "highp", "hvec2", "hvec3", "hvec4", "if", "iimage1D", "iimage1DArray", "iimage2D", "iimage2DArray", "iimage2DMS", "iimage2DMSArray", "iimage2DRect", "iimage3D", "iimageBuffer", "iimageCube", "iimageCubeArray", "image1D", "image1DArray", "image2D", "image2DArray", "image2DMS", "image2DMSArray", "image2DRect", "image3D", "imageBuffer", "imageCube", "imageCubeArray", "in", "inline", "inout", "input", "int", "interface", "invariant", "isampler1D", "isampler1DArray", "isampler2D", "isampler2DArray", "isampler2DMS", "isampler2DMSArray", "isampler2DRect", "isampler3D", "isamplerBuffer", "isamplerCube", "isamplerCubeArray", "isubpassInput", "isubpassInputMS", "itexture2D", "itexture2DArray", "itexture2DMS", "itexture2DMSArray", "itexture3D", "itextureBuffer", "itextureCube", "itextureCubeArray", "ivec2", "ivec3", "ivec4", "layout", "long", "lowp", "mat2", "mat2x2", "mat2x3", "mat2x4", "mat3", "mat3x2", "mat3x3", "mat3x4", "mat4", "mat4x2", "mat4x3", "mat4x4", "mediump", "namespace", "noinline", "noperspective", "out", "output", "partition", "patch", "precise", "precision", "public", "readonly", "resource", "restrict", "return", "sample", "sampler", "sampler1D", "sampler1DArray", "sampler1DArrayShadow", "sampler1DShadow", "sampler2D", "sampler2DArray", "sampler2DArrayShadow", "sampler2DMS", "sampler2DMSArray", "sampler2DRect", "sampler2DRectShadow", "sampler2DShadow", "sampler3D", "sampler3DRect", "samplerBuffer", "samplerCube", "samplerCubeArray", "samplerCubeArrayShadow", "samplerCubeShadow", "samplerShadow", "shared", "short", "sizeof", "smooth", "static", "struct", "subpassInput", "subpassInputMS", "subroutine", "superp", "switch", "template", "texture2D", "texture2DArray", "texture2DMS", "texture2DMSArray", "texture3D", "textureBuffer", "textureCube", "textureCubeArray", "this", "true", "typedef", "uimage1D", "uimage1DArray", "uimage2D", "uimage2DArray", "uimage2DMS", "uimage2DMSArray", "uimage2DRect", "uimage3D", "uimageBuffer", "uimageCube", "uimageCubeArray", "uint", "uniform", "union", "unsigned", "usampler1D", "usampler1DArray", "usampler2D", "usampler2DArray", "usampler2DMS", "usampler2DMSArray", "usampler2DRect", "usampler3D", "usamplerBuffer", "usamplerCube", "usamplerCubeArray", "using", "usubpassInput", "usubpassInputMS", "utexture2D", "utexture2DArray", "utexture2DMS", "utexture2DMSArray", "utexture3D", "utextureBuffer", "utextureCube", "utextureCubeArray", "uvec2", "uvec3", "uvec4", "varying", "vec2", "vec3", "vec4", "void", "volatile", "while", "writeonly" + }; + + ShaderAst::StatementPtr sanitizedAst = ShaderAst::Sanitize(shader, options); PreVisitor previsitor; previsitor.enabledOptions = states.enabledOptions;