mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Fix] (ShaderTranspiler): keep declared modern GLSL versions strict
Normalization rewrote every desktop core #version below 400 to 330 (and 400+ to 460), and a failed parse was retried at 460. Together these erased the declared version's rules: KHR-GL33 negative-compile cases (reserved names, parenthesized layout-qualifier values in a declared-420 shader, GLSL 4.5 mix() overloads at 330, precise in struct members) all compiled. Explicitly declared core versions >= 330 now keep their number, and the 460 retry only fires for sources whose directive carries the normalizer's own legacy marker - i.e. shaders that declared 110-150 (or nothing), which is the shader-pack compatibility case the retry exists for. Replaces the narrower arrays-of-arrays special case.
This commit is contained in:
@@ -220,18 +220,14 @@ namespace MobileGL {
|
||||
auto result = ParseShaderSource(lang, shaderType, source, attrib.flags);
|
||||
if (result) return result;
|
||||
|
||||
// Legacy desktop sources are normalized to "#version 330 core", which parses under
|
||||
// stricter rules than the 460 they used to be forced to: a shader declaring 330 while
|
||||
// using e.g. layout(binding=...) without the matching #extension line compiles on real
|
||||
// drivers but is rejected here. Retry once at 460 before reporting failure; a genuinely
|
||||
// broken shader fails both attempts and keeps its original diagnostics.
|
||||
//
|
||||
// Arrays of arrays are the exception: every desktop driver rejects them below 430
|
||||
// (the GL33 CTS requires the compile failure), so re-legalizing them at 460 would
|
||||
// trade a conformance failure for no real-world shader gain.
|
||||
if (result.error().log.find("arrays of arrays") != String::npos) {
|
||||
return result;
|
||||
}
|
||||
// Legacy desktop sources are normalized to "#version 330 core" (with a marker on the
|
||||
// directive), which parses under stricter rules than the 460 they used to be forced
|
||||
// to: a shader declaring 110-150 while using e.g. layout(binding=...) without the
|
||||
// matching #extension line compiles on real drivers but is rejected here. Retry once
|
||||
// at 460 before reporting failure; a genuinely broken shader fails both attempts and
|
||||
// keeps its original diagnostics. Application-declared 330+ sources carry no marker
|
||||
// and keep their declared version's strict rules (the GL CTS negative-compile cases
|
||||
// depend on that).
|
||||
String retrySource = source;
|
||||
if (!MG_Util::ShaderTranspiler::RetargetLegacyVersionDirectiveTo460(retrySource)) {
|
||||
return result;
|
||||
|
||||
@@ -688,6 +688,10 @@ namespace {
|
||||
return info;
|
||||
}
|
||||
|
||||
// Stamped onto the normalized directive when a legacy (or absent) desktop
|
||||
// version was rewritten to 330; consumed by RetargetLegacyVersionDirectiveTo460.
|
||||
constexpr const char* kNormalizedLegacyMarker = "/*mobilegl-normalized-legacy*/";
|
||||
|
||||
MobileGL::String GetNormalizedVersionDirective(const ShaderLanguageInfo& info) {
|
||||
if (info.profile == MobileGL::ShaderProfile::ES) {
|
||||
// Preserve the pre-existing behavior for standard lowercase "es" directives. MobileGL's Vulkan
|
||||
@@ -702,9 +706,23 @@ namespace {
|
||||
return "#version 460 compatibility\n";
|
||||
}
|
||||
|
||||
// An explicitly declared modern core version keeps its number: the GL CTS
|
||||
// negative-compile cases (reserved names, layout-qualifier forms, missing
|
||||
// overloads) rely on the declared version's rules, and raising it would
|
||||
// silently legalize them. gpu_shader5 opt-ins keep the 460 escalation -
|
||||
// Vulkan glslang's ARB_gpu_shader5 support is not complete enough alone.
|
||||
if (info.hasValidVersionDirective && info.version >= 330 && !info.enablesGpuShader5) {
|
||||
return "#version " + std::to_string(info.version) + " core\n";
|
||||
}
|
||||
|
||||
const bool useLegacyDesktopVersion =
|
||||
info.version < 400 && !info.enablesGpuShader5;
|
||||
return useLegacyDesktopVersion ? "#version 330 core\n" : "#version 460 core\n";
|
||||
// The trailing marker records that this 330 came from a legacy declaration
|
||||
// (or none at all), so the compile-failure retry may re-raise it to 460.
|
||||
// An application's own "#version 330" never carries it and keeps strict
|
||||
// 3.30 semantics.
|
||||
return useLegacyDesktopVersion ? MobileGL::String("#version 330 core ") + kNormalizedLegacyMarker + "\n"
|
||||
: "#version 460 core\n";
|
||||
}
|
||||
|
||||
void NormalizeVersionDirective(MobileGL::String& source, const ShaderLanguageInfo& info) {
|
||||
@@ -1306,6 +1324,18 @@ namespace MobileGL {
|
||||
// Only the set NormalizeVersionDirective downgraded: desktop core below 400. ES and
|
||||
// compatibility shaders keep whatever they declared.
|
||||
if (info.profile != ShaderProfile::Core || info.version >= 400) return false;
|
||||
// Only rescue MobileGL's own legacy normalization (marked on the directive line).
|
||||
// An application-declared "#version 330" keeps strict 3.30 semantics: raising it
|
||||
// would re-legalize the CTS negative-compile cases (reserved names, arrays of
|
||||
// arrays, missing overloads).
|
||||
SizeT lineEnd = source.find('\n', info.versionDirectiveStart);
|
||||
if (lineEnd == MobileGL::String::npos) {
|
||||
lineEnd = source.size();
|
||||
}
|
||||
const SizeT markerPos = source.find(kNormalizedLegacyMarker, info.versionDirectiveStart);
|
||||
if (markerPos == MobileGL::String::npos || markerPos > lineEnd) {
|
||||
return false;
|
||||
}
|
||||
|
||||
source.replace(info.versionDirectiveStart, info.versionDirectiveEnd - info.versionDirectiveStart,
|
||||
"#version 460 core\n");
|
||||
|
||||
Reference in New Issue
Block a user