[Fix] (MG_Util/ShaderTranspiler): stop stripping precision qualifiers - the strip corrupted "precision highp float;" into invalid syntax; glslang accepts and ignores them natively in 460 core (unblocks ~2000 GL CTS cases per backend)

This commit is contained in:
2026-07-16 01:50:33 -04:00
parent dc2f3a477b
commit 5331150cb9
2 changed files with 77 additions and 14 deletions
+75 -5
View File
@@ -112,8 +112,14 @@ void main() {
EXPECT_NE(source.find("out vec2 uv;"), String::npos);
EXPECT_EQ(source.find("attribute"), String::npos);
EXPECT_EQ(source.find("varying"), String::npos);
EXPECT_EQ(source.find("HIGHP_OR_DEFAULT"), String::npos);
EXPECT_EQ(source.find("#define"), String::npos);
// Precision-qualifier macros are left for glslang's own preprocessor to expand.
EXPECT_NE(source.find("#define HIGHP_OR_DEFAULT highp"), String::npos);
ShaderAttrib attrib{.shaderType = GL_VERTEX_SHADER, .sourceStr = source};
auto res = ShaderCompiler::CompileShader(attrib);
if (!res) {
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log << "\nsource:\n" << source;
}
}
TEST_F(ProgramUtilTest, PreprocessLegacyFragmentShaderModernizesGlmarkStyleSource) {
@@ -137,9 +143,14 @@ void main() {
EXPECT_NE(source.find("mg_FragColor = color;"), String::npos);
EXPECT_EQ(source.find("gl_FragColor"), String::npos);
EXPECT_EQ(source.find("texture2D"), String::npos);
EXPECT_EQ(source.find("MEDIUMP_OR_DEFAULT"), String::npos);
EXPECT_EQ(source.find("mediump"), String::npos);
EXPECT_EQ(source.find("#define"), String::npos);
// Precision-qualifier macros are left for glslang's own preprocessor to expand.
EXPECT_NE(source.find("#define MEDIUMP_OR_DEFAULT mediump"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
auto res = ShaderCompiler::CompileShader(attrib);
if (!res) {
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log << "\nsource:\n" << source;
}
}
TEST_F(ProgramUtilTest, PreprocessLegacyFragmentShaderModernizesFragData) {
@@ -166,6 +177,65 @@ void main() {
}
}
TEST_F(ProgramUtilTest, PreprocessKeepsDefaultPrecisionStatements) {
using namespace MG_Util::ShaderTranspiler;
// Mirrors the GL CTS helper shaders (e.g. glcPixelStorageModesTests): the old qualifier strip
// turned "precision highp float;" into invalid "precision float;". Precision qualifiers are
// legal (and ignored) in the forced 460 core profile, so they now pass through untouched.
String source = R"(#version 330
precision highp float;
precision mediump int;
out vec4 fragColor;
uniform highp sampler2D tex;
void main() {
highp vec2 uv = vec2(0.5);
fragColor = texture(tex, uv);
})";
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_NE(source.find("precision highp float;"), String::npos);
EXPECT_NE(source.find("precision mediump int;"), String::npos);
EXPECT_NE(source.find("uniform highp sampler2D tex;"), String::npos);
EXPECT_NE(source.find("fragColor = texture(tex, uv);"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
auto res = ShaderCompiler::CompileShader(attrib);
if (!res) {
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log << "\nsource:\n" << source;
}
}
TEST_F(ProgramUtilTest, PreprocessKeepsPrecisionInLegacyShaderForGlslang) {
using namespace MG_Util::ShaderTranspiler;
// Legacy ES-style shader: precision statements and qualifier macros are left for glslang
// (its preprocessor expands the #define; the 460 core parse ignores the qualifiers).
String source = R"(#define HIGHP_OR_DEFAULT highp
precision HIGHP_OR_DEFAULT float;
precision mediump int;
varying vec2 uv;
void main() {
mediump float shade = uv.x;
gl_FragColor = vec4(uv, shade, 1.0);
})";
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_NE(source.find("precision HIGHP_OR_DEFAULT float;"), String::npos);
EXPECT_NE(source.find("precision mediump int;"), String::npos);
EXPECT_NE(source.find("in vec2 uv;"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
auto res = ShaderCompiler::CompileShader(attrib);
if (!res) {
FAIL() << "errc: " << res.error().errc << "\nlog: " << res.error().log << "\nsource:\n" << source;
}
}
TEST_F(ProgramUtilTest, PreprocessFragmentShaderInjectsDepthRangeShim) {
using namespace MG_Util::ShaderTranspiler;
@@ -262,15 +262,8 @@ namespace {
}
void ModernizeLegacyGLSL(MobileGL::ShaderStage stage, MobileGL::String& source) {
RemoveDefineForIdentifier(source, "HIGHP_OR_DEFAULT");
RemoveDefineForIdentifier(source, "MEDIUMP_OR_DEFAULT");
RemoveDefineForIdentifier(source, "LOWP_OR_DEFAULT");
ReplaceIdentifier(source, "HIGHP_OR_DEFAULT", "");
ReplaceIdentifier(source, "MEDIUMP_OR_DEFAULT", "");
ReplaceIdentifier(source, "LOWP_OR_DEFAULT", "");
ReplaceIdentifier(source, "highp", "");
ReplaceIdentifier(source, "mediump", "");
ReplaceIdentifier(source, "lowp", "");
// Precision qualifiers (highp/mediump/lowp and default-precision statements) are legal and
// ignored in the forced "#version 460 core" profile, so glslang handles them natively.
ReplaceIdentifier(source, "texture2D", "texture");
ReplaceIdentifier(source, "texture2DProj", "textureProj");