diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp index dd1d36ba..9ceff58c 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderCompiler.cpp @@ -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; diff --git a/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp index 56c07f8c..4c97661e 100644 --- a/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp +++ b/MobileGL/MG_Util/ShaderTranspiler/ShaderSourceProcessor.cpp @@ -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");