mirror of
https://github.com/love2d/love.git
synced 2026-08-15 15:51:12 +02:00
shaders: ignore code in comments when parsing entry point functions.
Fixes #1581.
This commit is contained in:
+123
-18
@@ -22,6 +22,7 @@
|
||||
#include "Shader.h"
|
||||
#include "Graphics.h"
|
||||
#include "math/MathModule.h"
|
||||
#include "common/Range.h"
|
||||
|
||||
// glslang
|
||||
#include "libraries/glslang/glslang/Public/ShaderLang.h"
|
||||
@@ -425,6 +426,111 @@ static const Version versions[] =
|
||||
{ "#version 430 core", "#version 320 es" },
|
||||
};
|
||||
|
||||
enum CommentType
|
||||
{
|
||||
COMMENT_NONE,
|
||||
COMMENT_LINE,
|
||||
COMMENT_BLOCK,
|
||||
};
|
||||
|
||||
static void parseComments(const std::string &src, std::vector<Range> &comments)
|
||||
{
|
||||
CommentType commenttype = COMMENT_NONE;
|
||||
Range comment;
|
||||
|
||||
const char *srcbytes = src.data();
|
||||
size_t len = src.length();
|
||||
|
||||
for (size_t i = 0; i < len; i++)
|
||||
{
|
||||
char curchar = srcbytes[i];
|
||||
|
||||
if (commenttype == COMMENT_NONE)
|
||||
{
|
||||
if (curchar == '/' && i + 1 < len)
|
||||
{
|
||||
char nextchar = srcbytes[i + 1];
|
||||
if (nextchar == '/')
|
||||
{
|
||||
commenttype = COMMENT_LINE;
|
||||
comment = Range(i, 1);
|
||||
}
|
||||
else if (nextchar == '*')
|
||||
{
|
||||
commenttype = COMMENT_BLOCK;
|
||||
comment = Range(i, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (commenttype == COMMENT_LINE)
|
||||
{
|
||||
if (curchar == '\n')
|
||||
{
|
||||
commenttype = COMMENT_NONE;
|
||||
comment.last = i;
|
||||
comments.push_back(comment);
|
||||
}
|
||||
}
|
||||
else if (commenttype == COMMENT_BLOCK)
|
||||
{
|
||||
if (curchar == '/' && i > 0 && srcbytes[i - 1] == '*')
|
||||
{
|
||||
commenttype = COMMENT_NONE;
|
||||
comment.last = i;
|
||||
comments.push_back(comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (commenttype == COMMENT_LINE)
|
||||
{
|
||||
comment.last = len - 1;
|
||||
comments.push_back(comment);
|
||||
}
|
||||
}
|
||||
|
||||
static bool inComment(size_t i, const std::vector<Range> &comments)
|
||||
{
|
||||
Range r(i, 1);
|
||||
|
||||
for (const Range &comment : comments)
|
||||
{
|
||||
if (comment.contains(r))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool textSearch(const std::string &src, const std::string &str, const std::vector<Range> &comments)
|
||||
{
|
||||
size_t start = 0;
|
||||
size_t found = std::string::npos;
|
||||
|
||||
while ((found = src.find(str, start)) != std::string::npos)
|
||||
{
|
||||
if (!inComment(found, comments))
|
||||
return true;
|
||||
start = found + str.size();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool regexSearch(const std::string &src, const std::string &rstr, const std::vector<Range> &comments)
|
||||
{
|
||||
std::regex r(rstr);
|
||||
|
||||
for (auto it = std::sregex_iterator(src.begin(), src.end(), r); it != std::sregex_iterator(); it++)
|
||||
{
|
||||
const std::smatch &m = *it;
|
||||
if (!inComment(m.position(), comments))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Shader::Language getTargetLanguage(const std::string &src)
|
||||
{
|
||||
std::regex r("^\\s*#pragma language (\\w+)");
|
||||
@@ -435,33 +541,30 @@ static Shader::Language getTargetLanguage(const std::string &src)
|
||||
return lang;
|
||||
}
|
||||
|
||||
static Shader::EntryPoint getVertexEntryPoint(const std::string &src)
|
||||
static Shader::EntryPoint getVertexEntryPoint(const std::string &src, const std::vector<Range> &comments)
|
||||
{
|
||||
std::smatch m;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("void\\s+vertexmain\\s*\\(")))
|
||||
if (regexSearch(src, "void\\s+vertexmain\\s*\\(", comments))
|
||||
return Shader::ENTRYPOINT_RAW;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("vec4\\s+position\\s*\\(")))
|
||||
if (regexSearch(src, "vec4\\s+position\\s*\\(", comments))
|
||||
return Shader::ENTRYPOINT_HIGHLEVEL;
|
||||
|
||||
return Shader::ENTRYPOINT_NONE;
|
||||
}
|
||||
|
||||
static Shader::EntryPoint getPixelEntryPoint(const std::string &src, bool &mrt)
|
||||
static Shader::EntryPoint getPixelEntryPoint(const std::string &src, const std::vector<Range> &comments, bool &mrt)
|
||||
{
|
||||
mrt = false;
|
||||
std::smatch m;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("void\\s+pixelmain\\s*\\(")))
|
||||
if (regexSearch(src, "void\\s+pixelmain\\s*\\(", comments))
|
||||
return Shader::ENTRYPOINT_RAW;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("vec4\\s+effect\\s*\\(")))
|
||||
if (regexSearch(src, "vec4\\s+effect\\s*\\(", comments))
|
||||
return Shader::ENTRYPOINT_HIGHLEVEL;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("void\\s+effect\\s*\\(")))
|
||||
if (regexSearch(src, "void\\s+effect\\s*\\(", comments))
|
||||
{
|
||||
if (src.find("love_RenderTargets") != std::string::npos || src.find("love_Canvases") != std::string::npos)
|
||||
if (textSearch(src, "love_RenderTargets", comments) || textSearch(src, "love_Canvases", comments))
|
||||
mrt = true;
|
||||
return Shader::ENTRYPOINT_CUSTOM;
|
||||
}
|
||||
@@ -469,10 +572,9 @@ static Shader::EntryPoint getPixelEntryPoint(const std::string &src, bool &mrt)
|
||||
return Shader::ENTRYPOINT_NONE;
|
||||
}
|
||||
|
||||
static Shader::EntryPoint getComputeEntryPoint(const std::string &src) {
|
||||
std::smatch m;
|
||||
|
||||
if (std::regex_search(src, m, std::regex("void\\s+computemain\\s*\\(")))
|
||||
static Shader::EntryPoint getComputeEntryPoint(const std::string &src, const std::vector<Range> &comments)
|
||||
{
|
||||
if (regexSearch(src, "void\\s+computemain\\s*\\(", comments))
|
||||
return Shader::ENTRYPOINT_RAW;
|
||||
|
||||
return Shader::ENTRYPOINT_NONE;
|
||||
@@ -489,11 +591,14 @@ Shader *Shader::standardShaders[Shader::STANDARD_MAX_ENUM] = {nullptr};
|
||||
|
||||
Shader::SourceInfo Shader::getSourceInfo(const std::string &src)
|
||||
{
|
||||
std::vector<Range> comments;
|
||||
glsl::parseComments(src, comments);
|
||||
|
||||
SourceInfo info = {};
|
||||
info.language = glsl::getTargetLanguage(src);
|
||||
info.stages[SHADERSTAGE_VERTEX] = glsl::getVertexEntryPoint(src);
|
||||
info.stages[SHADERSTAGE_PIXEL] = glsl::getPixelEntryPoint(src, info.usesMRT);
|
||||
info.stages[SHADERSTAGE_COMPUTE] = glsl::getComputeEntryPoint(src);
|
||||
info.stages[SHADERSTAGE_VERTEX] = glsl::getVertexEntryPoint(src, comments);
|
||||
info.stages[SHADERSTAGE_PIXEL] = glsl::getPixelEntryPoint(src, comments, info.usesMRT);
|
||||
info.stages[SHADERSTAGE_COMPUTE] = glsl::getComputeEntryPoint(src, comments);
|
||||
if (info.stages[SHADERSTAGE_COMPUTE])
|
||||
info.language = LANGUAGE_GLSL4;
|
||||
return info;
|
||||
|
||||
Reference in New Issue
Block a user