[Improvement] (Shader/GLSL): Better function injections.

This commit is contained in:
BZLZHH 2025-07-12 22:41:57 +08:00
parent 98d4d51427
commit 75ddfe4100

View File

@ -345,7 +345,6 @@ std::string getCachedESSL(const char* glsl_code, uint essl_version) {
} else return "";
}
std::string GLSLtoGLSLES(const char* glsl_code, GLenum glsl_type, uint essl_version, uint glsl_version) {
std::string sha256_string(glsl_code);
sha256_string += "\n//" + std::to_string(MAJOR) + "." + std::to_string(MINOR) + "." + std::to_string(REVISION) + "|" + std::to_string(essl_version);
@ -435,28 +434,73 @@ static inline void replace_all(std::string& str, const std::string& from, const
}
}
static inline void inject_textureQueryLod(std::string& glsl) {
const std::string textureQueryLodCall = "textureQueryLod(";
const std::string textureQueryLodDef = "vec2 mg_textureQueryLod(sampler2D tex, vec2 uv)";
const std::string mainStart = "void main()";
static size_t find_insertion_point(const std::string& glsl) {
size_t pos = 0;
size_t insertion_point = 0;
// Already defined function
const auto def_loc = glsl.find(textureQueryLodDef);
if (def_loc != std::string::npos)
size_t version_pos = glsl.find("#version");
if (version_pos != std::string::npos) {
size_t version_end = glsl.find('\n', version_pos);
if (version_end == std::string::npos) {
version_end = glsl.length();
}
else {
version_end++;
}
insertion_point = version_end;
pos = version_end;
}
else {
insertion_point = 0;
pos = 0;
}
while (pos < glsl.length()) {
size_t line_begin = pos;
while (pos < glsl.length() && std::isspace(glsl[pos])) {
pos++;
}
if (pos >= glsl.length()) break;
if (glsl[pos] == '#') {
pos++;
while (pos < glsl.length() && std::isspace(glsl[pos])) {
pos++;
}
if (glsl.compare(pos, 9, "extension") == 0) {
size_t ext_end = glsl.find('\n', pos);
if (ext_end == std::string::npos) {
ext_end = glsl.length();
} else {
ext_end++;
}
insertion_point = ext_end;
pos = ext_end;
} else {
break;
}
} else {
break;
}
}
return insertion_point;
}
static void inject_textureQueryLod(std::string& glsl) {
const std::regex defRegex(R"(vec2\s+mg_textureQueryLod\s*\()", std::regex::ECMAScript);
if (glsl.find("textureQueryLod") == std::string::npos) {
return;
// Never called function
const auto call_loc = glsl.find(textureQueryLodCall);
if (call_loc == std::string::npos)
return;
const auto main_loc = glsl.find(mainStart);
// No main(), no inject
if (main_loc == std::string::npos)
}
if (std::regex_search(glsl, defRegex)) {
return;
}
const std::string textureQueryLodImpl = R"(
#define textureQueryLod mg_textureQueryLod
vec2 mg_textureQueryLod(sampler2D tex, vec2 uv) {
vec2 texSizeF = vec2(textureSize(tex, 0));
vec2 dFdx_uv = dFdx(uv * texSizeF);
@ -466,35 +510,30 @@ vec2 mg_textureQueryLod(sampler2D tex, vec2 uv) {
return vec2(lod);
}
)";
// Replace all calls to textureQueryLod()
replace_all(glsl, "textureQueryLod(", "mg_textureQueryLod(");
// Do injection here
glsl.insert(main_loc, "\n" + textureQueryLodImpl + "\n");
size_t insertPos = find_insertion_point(glsl);
glsl.insert(insertPos, "\n" + textureQueryLodImpl + "\n");
}
static inline void inject_temporal_filter(std::string& glsl) {
const std::string temporalFilterCall = "deferredOutput2 = GI_TemporalFilter()";
const std::string temporalFilterDef = "vec4 GI_TemporalFilter()";
const std::string mainStart = "void main()";
const std::regex defRegex(R"(vec4\s+GI_TemporalFilter\s*\()", std::regex::ECMAScript);
// Already defined function
const auto def_loc = glsl.find(temporalFilterDef);
if (def_loc != std::string::npos)
if (glsl.find("GI_TemporalFilter") == std::string::npos) {
return;
// Never called function
const auto call_loc = glsl.find(temporalFilterCall);
if (call_loc == std::string::npos)
}
if (std::regex_search(glsl, defRegex)) {
return;
}
const std::regex uniformRegex(R"(^\s*(?:layout\s*\([^)]*\)\s*)?uniform\s+\w+(?:\s*\[\s*\d+\s*\])?\s+\w+(?:\s*\[\s*\d+\s*\])?\s*;.*$)", std::regex::ECMAScript | std::regex::multiline);
std::sregex_iterator it(glsl.begin(), glsl.end(), uniformRegex);
std::sregex_iterator end;
size_t insertPos = 0;
for (; it != end; ++it) {
insertPos = it->position() + it->length();
}
const auto main_loc = glsl.find(mainStart);
// No main(), no inject
if (main_loc == std::string::npos)
return;
const std::string GI_TemporalFilter = R"(
const std::string GI_TemporalFilterImpl = R"(
vec4 GI_TemporalFilter() {
vec2 uv = gl_FragCoord.xy / screenSize;
uv += taaJitter * pixelSize;
@ -518,10 +557,8 @@ vec4 GI_TemporalFilter() {
return filteredGI;
}
)";
// Do injection here
glsl.insert(main_loc, "\n" + GI_TemporalFilter + "\n");
glsl.insert(insertPos, "\n" + GI_TemporalFilterImpl + "\n");
}
#define xstr(s) str(s)
#define str(s) #s