mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-09 04:38:30 +09:00
[Chore] (MG_Backend/DirectVulkan): make Photon fix a SPIR-V patch rather than source-level
This commit is contained in:
@@ -13,253 +13,10 @@
|
||||
namespace {
|
||||
using MobileGL::SizeT;
|
||||
|
||||
struct FlattenedVaryingMember {
|
||||
const char* typeName;
|
||||
const char* memberName;
|
||||
};
|
||||
|
||||
constexpr FlattenedVaryingMember kDailyWeatherVariationMembers[] = {
|
||||
{"vec2", "clouds_cumulus_coverage"},
|
||||
{"vec2", "clouds_altocumulus_coverage"},
|
||||
{"vec2", "clouds_cirrus_coverage"},
|
||||
{"float", "clouds_cumulus_congestus_amount"},
|
||||
{"float", "clouds_stratus_amount"},
|
||||
{"float", "fogginess"},
|
||||
{"float", "aurora_amount"},
|
||||
{"float", "nlc_amount"},
|
||||
{"mat2x3", "aurora_colors"},
|
||||
};
|
||||
|
||||
bool IsIdentifierChar(char ch) {
|
||||
return (ch >= '0' && ch <= '9') || (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || ch == '_';
|
||||
}
|
||||
|
||||
bool HasIdentifierBoundaries(const MobileGL::String& source, SizeT pos, SizeT length) {
|
||||
const bool hasLeftBoundary = pos == 0 || !IsIdentifierChar(source[pos - 1]);
|
||||
const SizeT end = pos + length;
|
||||
const bool hasRightBoundary = end >= source.size() || !IsIdentifierChar(source[end]);
|
||||
return hasLeftBoundary && hasRightBoundary;
|
||||
}
|
||||
|
||||
SizeT FindToken(const MobileGL::String& source, const MobileGL::String& token, SizeT start = 0) {
|
||||
SizeT pos = start;
|
||||
while ((pos = source.find(token, pos)) != MobileGL::String::npos) {
|
||||
if (HasIdentifierBoundaries(source, pos, token.size())) {
|
||||
return pos;
|
||||
}
|
||||
pos += token.size();
|
||||
}
|
||||
return MobileGL::String::npos;
|
||||
}
|
||||
|
||||
void ReplaceTokenOccurrencesInRange(MobileGL::String& source, SizeT rangeStart, SizeT rangeEnd,
|
||||
const MobileGL::String& from, const MobileGL::String& to) {
|
||||
SizeT pos = rangeStart;
|
||||
while ((pos = source.find(from, pos)) != MobileGL::String::npos && pos < rangeEnd) {
|
||||
if (!HasIdentifierBoundaries(source, pos, from.size())) {
|
||||
pos += from.size();
|
||||
continue;
|
||||
}
|
||||
|
||||
source.replace(pos, from.size(), to);
|
||||
const auto delta = static_cast<std::ptrdiff_t>(to.size()) - static_cast<std::ptrdiff_t>(from.size());
|
||||
rangeEnd = static_cast<SizeT>(static_cast<std::ptrdiff_t>(rangeEnd) + delta);
|
||||
pos += to.size();
|
||||
}
|
||||
}
|
||||
|
||||
void ReplaceAll(MobileGL::String& source, const MobileGL::String& from, const MobileGL::String& to) {
|
||||
SizeT pos = 0;
|
||||
while ((pos = source.find(from, pos)) != MobileGL::String::npos) {
|
||||
source.replace(pos, from.size(), to);
|
||||
pos += to.size();
|
||||
}
|
||||
}
|
||||
|
||||
MobileGL::String TrimWhitespace(const MobileGL::String& input) {
|
||||
SizeT begin = 0;
|
||||
while (begin < input.size() && std::isspace(static_cast<unsigned char>(input[begin]))) {
|
||||
begin++;
|
||||
}
|
||||
|
||||
SizeT end = input.size();
|
||||
while (end > begin && std::isspace(static_cast<unsigned char>(input[end - 1]))) {
|
||||
end--;
|
||||
}
|
||||
|
||||
return input.substr(begin, end - begin);
|
||||
}
|
||||
|
||||
bool FindFunctionBody(const MobileGL::String& source, const MobileGL::String& signature, SizeT* bodyStart,
|
||||
SizeT* bodyEnd) {
|
||||
const SizeT signaturePos = source.find(signature);
|
||||
if (signaturePos == MobileGL::String::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const SizeT bracePos = source.find('{', signaturePos + signature.size());
|
||||
if (bracePos == MobileGL::String::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int depth = 1;
|
||||
for (SizeT pos = bracePos + 1; pos < source.size(); pos++) {
|
||||
if (source[pos] == '{') {
|
||||
depth++;
|
||||
} else if (source[pos] == '}') {
|
||||
depth--;
|
||||
if (depth == 0) {
|
||||
*bodyStart = bracePos + 1;
|
||||
*bodyEnd = pos;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void RenameDailyWeatherVariationHelperLocal(MobileGL::String& source) {
|
||||
constexpr const char* kHelperSignature = "DailyWeatherVariation get_daily_weather_variation()";
|
||||
constexpr const char* kInterfaceName = "daily_weather_variation";
|
||||
constexpr const char* kLocalName = "mg_daily_weather_variation_local";
|
||||
|
||||
SizeT bodyStart = 0;
|
||||
SizeT bodyEnd = 0;
|
||||
if (!FindFunctionBody(source, kHelperSignature, &bodyStart, &bodyEnd)) {
|
||||
return;
|
||||
}
|
||||
|
||||
ReplaceTokenOccurrencesInRange(source, bodyStart, bodyEnd, kInterfaceName, kLocalName);
|
||||
}
|
||||
|
||||
bool RewriteDailyWeatherVariationInterface(MobileGL::ShaderStage stage, MobileGL::String& source) {
|
||||
using MobileGL::ShaderStage;
|
||||
|
||||
if (stage != ShaderStage::Vertex && stage != ShaderStage::Fragment) {
|
||||
return false;
|
||||
}
|
||||
|
||||
constexpr const char* kTypeName = "DailyWeatherVariation";
|
||||
constexpr const char* kInterfaceName = "daily_weather_variation";
|
||||
constexpr const char* kTempName = "mg_daily_weather_variation_tmp";
|
||||
const MobileGL::String declarationNeedle = MobileGL::String(kTypeName) + " " + kInterfaceName + ";";
|
||||
|
||||
RenameDailyWeatherVariationHelperLocal(source);
|
||||
|
||||
const SizeT declarationPos = source.find(declarationNeedle);
|
||||
if (declarationPos == MobileGL::String::npos) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SizeT lineStart = source.rfind('\n', declarationPos);
|
||||
lineStart = (lineStart == MobileGL::String::npos) ? 0 : lineStart + 1;
|
||||
SizeT lineEnd = source.find('\n', declarationPos);
|
||||
if (lineEnd == MobileGL::String::npos) {
|
||||
lineEnd = source.size();
|
||||
}
|
||||
|
||||
const MobileGL::String declarationLine = source.substr(lineStart, lineEnd - lineStart);
|
||||
MOBILEGL_ASSERT(declarationLine.find("layout(") == MobileGL::String::npos,
|
||||
"PreprocessShaderSource: unexpected explicit layout on DailyWeatherVariation interface in stage=%d",
|
||||
static_cast<int>(stage));
|
||||
|
||||
const bool hasInputQualifier = declarationLine.find(" in ") != MobileGL::String::npos ||
|
||||
declarationLine.rfind("in ", 0) == 0;
|
||||
const bool hasOutputQualifier = declarationLine.find(" out ") != MobileGL::String::npos ||
|
||||
declarationLine.rfind("out ", 0) == 0;
|
||||
MOBILEGL_ASSERT(hasInputQualifier != hasOutputQualifier,
|
||||
"PreprocessShaderSource: expected a single in/out qualifier on DailyWeatherVariation interface in stage=%d line='%s'",
|
||||
static_cast<int>(stage), declarationLine.c_str());
|
||||
|
||||
const MobileGL::String qualifierPrefix = source.substr(lineStart, declarationPos - lineStart);
|
||||
MobileGL::String replacementDeclaration;
|
||||
for (const auto& member : kDailyWeatherVariationMembers) {
|
||||
replacementDeclaration += qualifierPrefix;
|
||||
replacementDeclaration += member.typeName;
|
||||
replacementDeclaration += " ";
|
||||
replacementDeclaration += kInterfaceName;
|
||||
replacementDeclaration += "_";
|
||||
replacementDeclaration += member.memberName;
|
||||
replacementDeclaration += ";\n";
|
||||
}
|
||||
source.replace(lineStart, lineEnd - lineStart + (lineEnd < source.size() ? 1 : 0), replacementDeclaration);
|
||||
|
||||
SizeT assignPos = FindToken(source, kInterfaceName);
|
||||
while (assignPos != MobileGL::String::npos) {
|
||||
SizeT probe = assignPos + strlen(kInterfaceName);
|
||||
while (probe < source.size() && std::isspace(static_cast<unsigned char>(source[probe]))) {
|
||||
probe++;
|
||||
}
|
||||
|
||||
if (probe >= source.size() || source[probe] != '=') {
|
||||
assignPos = FindToken(source, kInterfaceName, assignPos + strlen(kInterfaceName));
|
||||
continue;
|
||||
}
|
||||
|
||||
SizeT statementStart = source.rfind('\n', assignPos);
|
||||
statementStart = (statementStart == MobileGL::String::npos) ? 0 : statementStart + 1;
|
||||
for (SizeT i = statementStart; i < assignPos; i++) {
|
||||
MOBILEGL_ASSERT(std::isspace(static_cast<unsigned char>(source[i])),
|
||||
"PreprocessShaderSource: unexpected inline DailyWeatherVariation assignment in stage=%d",
|
||||
static_cast<int>(stage));
|
||||
}
|
||||
|
||||
const MobileGL::String indentation = source.substr(statementStart, assignPos - statementStart);
|
||||
const SizeT statementEnd = source.find(';', probe);
|
||||
MOBILEGL_ASSERT(statementEnd != MobileGL::String::npos,
|
||||
"PreprocessShaderSource: missing ';' after DailyWeatherVariation assignment in stage=%d",
|
||||
static_cast<int>(stage));
|
||||
|
||||
const MobileGL::String rhsExpression = TrimWhitespace(source.substr(probe + 1, statementEnd - probe - 1));
|
||||
MobileGL::String replacementStatement;
|
||||
replacementStatement += indentation;
|
||||
replacementStatement += "{\n";
|
||||
replacementStatement += indentation;
|
||||
replacementStatement += " DailyWeatherVariation ";
|
||||
replacementStatement += kTempName;
|
||||
replacementStatement += " = ";
|
||||
replacementStatement += rhsExpression;
|
||||
replacementStatement += ";\n";
|
||||
for (const auto& member : kDailyWeatherVariationMembers) {
|
||||
replacementStatement += indentation;
|
||||
replacementStatement += " ";
|
||||
replacementStatement += kInterfaceName;
|
||||
replacementStatement += "_";
|
||||
replacementStatement += member.memberName;
|
||||
replacementStatement += " = ";
|
||||
replacementStatement += kTempName;
|
||||
replacementStatement += ".";
|
||||
replacementStatement += member.memberName;
|
||||
replacementStatement += ";\n";
|
||||
}
|
||||
replacementStatement += indentation;
|
||||
replacementStatement += "}";
|
||||
if (statementEnd + 1 < source.size() && source[statementEnd + 1] == '\n') {
|
||||
replacementStatement += "\n";
|
||||
source.replace(statementStart, statementEnd - statementStart + 2, replacementStatement);
|
||||
} else {
|
||||
source.replace(statementStart, statementEnd - statementStart + 1, replacementStatement);
|
||||
}
|
||||
|
||||
assignPos = FindToken(source, kInterfaceName, statementStart + replacementStatement.size());
|
||||
}
|
||||
|
||||
for (const auto& member : kDailyWeatherVariationMembers) {
|
||||
const MobileGL::String from = MobileGL::String(kInterfaceName) + "." + member.memberName;
|
||||
const MobileGL::String to = MobileGL::String(kInterfaceName) + "_" + member.memberName;
|
||||
ReplaceAll(source, from, to);
|
||||
}
|
||||
|
||||
MOBILEGL_ASSERT(source.find(MobileGL::String(kTypeName) + " " + kInterfaceName + ";") == MobileGL::String::npos,
|
||||
"PreprocessShaderSource: unrewritten DailyWeatherVariation interface declaration remained in stage=%d",
|
||||
static_cast<int>(stage));
|
||||
MOBILEGL_ASSERT(source.find(MobileGL::String(kInterfaceName) + ".") == MobileGL::String::npos,
|
||||
"PreprocessShaderSource: unrewritten DailyWeatherVariation member access remained in stage=%d",
|
||||
static_cast<int>(stage));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool HasSingleLineFunctionDefinition(const MobileGL::String& source, const MobileGL::String& functionName) {
|
||||
SizeT lineStart = 0;
|
||||
while (lineStart < source.size()) {
|
||||
@@ -351,8 +108,13 @@ namespace MobileGL {
|
||||
SizeT linedirPos = source.find("#line");
|
||||
while (linedirPos != String::npos) {
|
||||
SizeT newlinePos = source.find('\n', linedirPos);
|
||||
// + length of "\n"
|
||||
source = source.replace(linedirPos, newlinePos - linedirPos + 1, "");
|
||||
if (newlinePos == String::npos) {
|
||||
source.erase(linedirPos);
|
||||
break;
|
||||
}
|
||||
|
||||
// Preserve a line break so adjacent preprocessor directives do not merge.
|
||||
source = source.replace(linedirPos, newlinePos - linedirPos + 1, "\n");
|
||||
linedirPos = source.find("#line", linedirPos);
|
||||
}
|
||||
|
||||
@@ -407,8 +169,6 @@ namespace MobileGL {
|
||||
RenameBuiltinShadowingFunction(source, "round", "mg_round");
|
||||
RenameBuiltinShadowingFunction(source, "tanh", "mg_tanh");
|
||||
RenameBuiltinShadowingFunction(source, "fma", "mg_fma");
|
||||
|
||||
RewriteDailyWeatherVariationInterface(stage, source);
|
||||
}
|
||||
|
||||
} // namespace ShaderTranspiler
|
||||
|
||||
Reference in New Issue
Block a user