GPU: Shader Preprocess: Processing time optimizations
Guarding expensive regex computation by much cheaper checks to reduce compilation time. Compiling `time ninja -j 1 bf_draw_shaders` On MacOS M1 Max (debug build with glsl_preprocess optimization turned on): Before 13.01 sec After 9.08 sec Pull Request: https://projects.blender.org/blender/blender/pulls/138336
This commit is contained in:
committed by
Clément Foucault
parent
bbfc97ad6f
commit
f844ed7869
@@ -590,33 +590,32 @@ class Preprocessor {
|
||||
std::string::npos;
|
||||
using namespace metadata;
|
||||
/* TODO: This can trigger false positive caused by disabled #if blocks. */
|
||||
std::regex regex(
|
||||
"("
|
||||
"gl_FragCoord|"
|
||||
"gl_FrontFacing|"
|
||||
"gl_GlobalInvocationID|"
|
||||
"gl_InstanceID|"
|
||||
"gl_LocalInvocationID|"
|
||||
"gl_LocalInvocationIndex|"
|
||||
"gl_NumWorkGroup|"
|
||||
"gl_PointCoord|"
|
||||
"gl_PointSize|"
|
||||
"gl_PrimitiveID|"
|
||||
"gl_VertexID|"
|
||||
"gl_WorkGroupID|"
|
||||
"gl_WorkGroupSize|"
|
||||
"drw_debug_|"
|
||||
std::string tokens[] = {"gl_FragCoord",
|
||||
"gl_FrontFacing",
|
||||
"gl_GlobalInvocationID",
|
||||
"gl_InstanceID",
|
||||
"gl_LocalInvocationID",
|
||||
"gl_LocalInvocationIndex",
|
||||
"gl_NumWorkGroup",
|
||||
"gl_PointCoord",
|
||||
"gl_PointSize",
|
||||
"gl_PrimitiveID",
|
||||
"gl_VertexID",
|
||||
"gl_WorkGroupID",
|
||||
"gl_WorkGroupSize",
|
||||
"drw_debug_",
|
||||
#ifdef WITH_GPU_SHADER_ASSERT
|
||||
"assert|"
|
||||
"assert",
|
||||
#endif
|
||||
"printf"
|
||||
")");
|
||||
regex_global_search(str, regex, [&](const std::smatch &match) {
|
||||
if (skip_drw_debug && match[0].str() == "drw_debug_") {
|
||||
return;
|
||||
"printf"};
|
||||
for (auto &token : tokens) {
|
||||
if (skip_drw_debug && token == "drw_debug_") {
|
||||
continue;
|
||||
}
|
||||
metadata.builtins.emplace_back(Builtin(hash(match[0].str())));
|
||||
});
|
||||
if (str.find(token) != std::string::npos) {
|
||||
metadata.builtins.emplace_back(Builtin(hash(token)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ReportErrorF>
|
||||
@@ -773,14 +772,30 @@ class Preprocessor {
|
||||
}
|
||||
|
||||
/* To be run before `argument_decorator_macro_injection()`. */
|
||||
std::string argument_reference_mutation(const std::string &str)
|
||||
std::string argument_reference_mutation(std::string &str)
|
||||
{
|
||||
/* Next two regexes are expensive. Check if they are needed at all. */
|
||||
bool valid_match = false;
|
||||
reference_search(str, [&](int parenthesis_depth, int bracket_depth, char &c) {
|
||||
/* Check if inside a function signature.
|
||||
* Check parenthesis_depth == 2 for array references. */
|
||||
if ((parenthesis_depth == 1 || parenthesis_depth == 2) && bracket_depth == 0) {
|
||||
valid_match = true;
|
||||
/* Modify the & into @ to make sure we only match these references in the regex
|
||||
* below. @ being forbidden in the shader language, it is safe to use a temp
|
||||
* character. */
|
||||
c = '@';
|
||||
}
|
||||
});
|
||||
if (!valid_match) {
|
||||
return str;
|
||||
}
|
||||
/* Remove parenthesis first. */
|
||||
/* Example: `float (&var)[2]` > `float &var[2]` */
|
||||
std::regex regex_parenthesis(R"((\w+ )\(&(\w+)\))");
|
||||
std::string out = std::regex_replace(str, regex_parenthesis, "$1&$2");
|
||||
std::regex regex_parenthesis(R"((\w+ )\(@(\w+)\))");
|
||||
std::string out = std::regex_replace(str, regex_parenthesis, "$1@$2");
|
||||
/* Example: `const float &var[2]` > `inout float var[2]` */
|
||||
std::regex regex(R"((?:const)?(\s*)(\w+)\s+\&(\w+)(\[\d*\])?)");
|
||||
std::regex regex(R"((?:const)?(\s*)(\w+)\s+\@(\w+)(\[\d*\])?)");
|
||||
return std::regex_replace(out, regex, "$1 inout $2 $3$4");
|
||||
}
|
||||
|
||||
@@ -801,9 +816,20 @@ class Preprocessor {
|
||||
/* TODO(fclem): Too many false positive and false negative to be applied to python shaders. */
|
||||
void matrix_constructor_linting(const std::string &str, report_callback report_error)
|
||||
{
|
||||
/* The following regex is expensive. Do a quick early out scan. */
|
||||
if (str.find("mat") == std::string::npos && str.find("float") == std::string::npos) {
|
||||
return;
|
||||
}
|
||||
/* Example: `mat4(other_mat)`. */
|
||||
std::regex regex(R"(\s+(mat(\d|\dx\d)|float\dx\d)\([^,\s\d]+\))");
|
||||
std::regex regex(R"(\s(?:mat(?:\d|\dx\d)|float\dx\d)\()");
|
||||
regex_global_search(str, regex, [&](const std::smatch &match) {
|
||||
std::string args = get_content_between_balanced_pair("(" + match.suffix().str(), '(', ')');
|
||||
int arg_count = split_string_not_between_balanced_pair(args, ',', '(', ')').size();
|
||||
bool has_floating_point_arg = args.find('.') != std::string::npos;
|
||||
/* TODO(fclem): Check if arg count matches matrix type. */
|
||||
if (arg_count != 1 || has_floating_point_arg) {
|
||||
return;
|
||||
}
|
||||
/* This only catches some invalid usage. For the rest, the CI will catch them. */
|
||||
const char *msg =
|
||||
"Matrix constructor is not cross API compatible. "
|
||||
|
||||
Reference in New Issue
Block a user