mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-12 22:28:32 +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 "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 MobileGL {
|
||||||
namespace MG_Util {
|
namespace MG_Util {
|
||||||
namespace ShaderTranspiler {
|
namespace ShaderTranspiler {
|
||||||
@@ -75,6 +158,10 @@ namespace MobileGL {
|
|||||||
source = replacement;
|
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
|
} // namespace ShaderTranspiler
|
||||||
|
|||||||
Reference in New Issue
Block a user