mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 20:58:31 +09:00
[Fix] (MG_Util/ShaderTranspiler): add preprocessing to remove name-collided glsl functions
This commit is contained in:
@@ -8,6 +8,89 @@
|
||||
|
||||
#include "ShaderSourceProcessor.h"
|
||||
|
||||
#include <cctype>
|
||||
|
||||
namespace {
|
||||
using MobileGL::SizeT;
|
||||
|
||||
bool IsIdentifierChar(char ch) {
|
||||
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_';
|
||||
}
|
||||
|
||||
bool HasSingleLineFunctionDefinition(const MobileGL::String& source, const MobileGL::String& functionName) {
|
||||
SizeT lineStart = 0;
|
||||
while (lineStart < source.size()) {
|
||||
SizeT lineEnd = source.find('\n', lineStart);
|
||||
if (lineEnd == MobileGL::String::npos) {
|
||||
lineEnd = source.size();
|
||||
}
|
||||
|
||||
SizeT functionPos = source.find(functionName, lineStart);
|
||||
while (functionPos != MobileGL::String::npos && functionPos < lineEnd) {
|
||||
const bool hasLeftBoundary = functionPos == 0 || !IsIdentifierChar(source[functionPos - 1]);
|
||||
const SizeT functionEnd = functionPos + functionName.size();
|
||||
const bool hasRightBoundary =
|
||||
functionEnd >= source.size() || !IsIdentifierChar(source[functionEnd]);
|
||||
if (hasLeftBoundary && hasRightBoundary) {
|
||||
SizeT probe = functionEnd;
|
||||
while (probe < lineEnd && std::isspace(static_cast<unsigned char>(source[probe]))) {
|
||||
probe++;
|
||||
}
|
||||
if (probe < lineEnd && source[probe] == '(') {
|
||||
const SizeT closingParen = source.find(')', probe);
|
||||
if (closingParen != MobileGL::String::npos && closingParen < lineEnd) {
|
||||
probe = closingParen + 1;
|
||||
while (probe < lineEnd && std::isspace(static_cast<unsigned char>(source[probe]))) {
|
||||
probe++;
|
||||
}
|
||||
if (probe < lineEnd && source[probe] == '{') {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
functionPos = source.find(functionName, functionPos + functionName.size());
|
||||
}
|
||||
|
||||
lineStart = lineEnd + 1;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenameFunctionInvocations(MobileGL::String& source, const MobileGL::String& from, const MobileGL::String& to) {
|
||||
SizeT pos = 0;
|
||||
while ((pos = source.find(from, pos)) != MobileGL::String::npos) {
|
||||
const bool hasLeftBoundary = pos == 0 || !IsIdentifierChar(source[pos - 1]);
|
||||
const SizeT end = pos + from.size();
|
||||
const bool hasRightBoundary = end >= source.size() || !IsIdentifierChar(source[end]);
|
||||
|
||||
SizeT probe = end;
|
||||
while (probe < source.size() && std::isspace(static_cast<unsigned char>(source[probe]))) {
|
||||
probe++;
|
||||
}
|
||||
|
||||
if (hasLeftBoundary && hasRightBoundary && probe < source.size() && source[probe] == '(') {
|
||||
source.replace(pos, from.size(), to);
|
||||
pos += to.size();
|
||||
continue;
|
||||
}
|
||||
|
||||
pos = end;
|
||||
}
|
||||
}
|
||||
|
||||
void RenameBuiltinShadowingFunction(MobileGL::String& source, const char* from, const char* to) {
|
||||
const MobileGL::String fromName = from;
|
||||
if (!HasSingleLineFunctionDefinition(source, fromName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
RenameFunctionInvocations(source, fromName, to);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace MobileGL {
|
||||
namespace MG_Util {
|
||||
namespace ShaderTranspiler {
|
||||
@@ -75,6 +158,10 @@ namespace MobileGL {
|
||||
source = replacement;
|
||||
}
|
||||
}
|
||||
|
||||
// Some shader packs define helpers with built-in GLSL names such as round().
|
||||
// These may pass OpenGL-style validation but fail when recompiled for Vulkan/SPIR-V generation.
|
||||
RenameBuiltinShadowingFunction(source, "round", "mg_round");
|
||||
}
|
||||
|
||||
} // namespace ShaderTranspiler
|
||||
|
||||
Reference in New Issue
Block a user