[Test] (MG_Test): catch the unit tests up with three deliberate behaviour changes

ctest -L unit had been failing 13 of its 418 cases, all of them tests left asserting
what the code did before a commit that changed it on purpose:

- "restore target GL version to 3.3" put the advertised target back after the
  experimental 4.6 run, but the two Voxy sanity tests still demanded 4.6. The
  extensions they really care about are all still advertised, so assert 3.3 and drop
  the now-meaningless AtExperimentalCTSVersion from their names.
- "support rectangle textures where the emulation is exact" made every desktop-only
  target supported - rectangle included, stored as a plain 2D - while the texture
  test still expected rectangle to be rejected.
- "keep declared modern GLSL versions strict" changed two things at once: a
  normalized legacy directive now carries a marker on its line, so the ten tests
  matching "#version 330 core\n" whole no longer match; and a version the
  application declared itself is no longer raised to 460, so the sources declaring
  330/400 keep their own number and only MobileGL's own normalization is retargeted.

Test expectations follow, rather than the implementation being bent back: each of
the three changes is the intended behaviour and is argued for where it was made. The
retry test now drives the 460 escalation from a legacy "#version 130" source, which
is the only thing that is still rescued, and gained a case pinning the other half of
that contract - an application-declared "#version 330" stays at 330.

418/418 unit tests pass.
This commit is contained in:
BZLZHH
2026-08-02 09:04:16 -04:00
parent 2f2f95498f
commit 86c00bdf18
3 changed files with 49 additions and 28 deletions
+35 -19
View File
@@ -223,7 +223,7 @@ void main() {
PreprocessShaderSource(ShaderStage::Vertex, source);
EXPECT_EQ(source.find("#version 330 core\n"), 0);
EXPECT_EQ(source.find("#version 330 core "), 0);
EXPECT_NE(source.find("in vec3 position;"), String::npos);
EXPECT_NE(source.find("out vec2 uv;"), String::npos);
EXPECT_EQ(source.find("attribute"), String::npos);
@@ -323,7 +323,7 @@ void main() {
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 330 core\n"), 0);
EXPECT_EQ(source.find("#version 330 core "), 0);
EXPECT_NE(source.find("out vec4 mg_FragColor;\n"), String::npos);
EXPECT_NE(source.find("in vec2 uv;"), String::npos);
EXPECT_NE(source.find("texture(texture0, uv)"), String::npos);
@@ -379,7 +379,7 @@ void main() {
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 330 core\n"), 0);
EXPECT_EQ(source.find("#version 330 core "), 0);
EXPECT_NE(source.find("vec4 sample = texture(DiffuseSampler"), String::npos);
EXPECT_NE(source.find("totalAlpha = totalAlpha + sample.a;"), String::npos);
EXPECT_NE(source.find("float totalSamples = 0.0;"), String::npos);
@@ -405,7 +405,7 @@ void main() {
)";
PreprocessShaderSource(ShaderStage::Vertex, vertexSource);
EXPECT_EQ(vertexSource.find("#version 330 core\n"), 0);
EXPECT_EQ(vertexSource.find("#version 330 core "), 0);
EXPECT_NE(vertexSource.find("in vec3 sample;"), String::npos);
ShaderAttrib vertexAttrib{.shaderType = GL_VERTEX_SHADER, .sourceStr = vertexSource};
@@ -425,7 +425,7 @@ void main() {
)";
PreprocessShaderSource(ShaderStage::Fragment, fragmentSource);
EXPECT_EQ(fragmentSource.find("#version 330 core\n"), 0);
EXPECT_EQ(fragmentSource.find("#version 330 core "), 0);
EXPECT_NE(fragmentSource.find("uniform sampler2D sample;"), String::npos);
EXPECT_NE(fragmentSource.find("texture(sample, texCoord)"), String::npos);
@@ -483,7 +483,9 @@ void main() {
)";
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 460 core\n"), 0);
// An explicitly declared modern core version keeps its number (see "keep declared modern
// GLSL versions strict"); only the BOM goes.
EXPECT_EQ(source.find(String(inputVersion) + "\n"), 0);
EXPECT_EQ(source.find("\xef\xbb\xbf"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
@@ -568,10 +570,12 @@ void main() {
)";
PreprocessShaderSource(ShaderStage::Fragment, source);
const SizeT versionPos = source.find("#version 330 core\n");
const SizeT versionPos = source.find("#version 330 core ");
const SizeT outputPos = source.find("out vec4 mg_FragColor;\n");
EXPECT_NE(versionPos, String::npos);
EXPECT_EQ(outputPos, versionPos + std::strlen("#version 330 core\n"));
// The normalized directive carries a marker recording that this 330 came from a legacy
// declaration, so measure the line rather than assuming its length.
EXPECT_EQ(outputPos, source.find('\n', versionPos) + 1);
EXPECT_NE(source.find("// #version 460 core"), String::npos);
// This #line sits ahead of the version directive, where GLSL would never have honoured it, so
// it is still dropped. Directives that follow the version line are kept - see
@@ -684,7 +688,7 @@ void main() {
}
}
TEST_F(ProgramUtilTest, PreprocessModernSampleQualifierStaysAtVersion460) {
TEST_F(ProgramUtilTest, PreprocessModernSampleQualifierStaysAtItsDeclaredVersion) {
using namespace MG_Util::ShaderTranspiler;
String source = R"(#version 400 core
@@ -697,7 +701,7 @@ void main() {
)";
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 460 core\n"), 0);
EXPECT_EQ(source.find("#version 400 core\n"), 0);
EXPECT_NE(source.find("sample in vec4 interpolatedColor;"), String::npos);
ShaderAttrib attrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
@@ -746,7 +750,7 @@ void main() {
PreprocessShaderSource(ShaderStage::Fragment, source);
EXPECT_EQ(source.find("#version 330 core\n"), 0);
EXPECT_EQ(source.find("#version 330 core "), 0);
EXPECT_NE(source.find("layout(location = 0) out vec4 mg_FragData[8];\n"), String::npos);
EXPECT_NE(source.find("mg_FragData[0] = vec4(1.0);"), String::npos);
EXPECT_NE(source.find("mg_FragData[1].a = 0.5;"), String::npos);
@@ -902,16 +906,17 @@ TEST_F(ProgramUtilTest, CompileSimpleVertexShader) {
}
// Legacy desktop sources are normalized to "#version 330 core", which is stricter than the 460 they
// used to be forced to. A shader declaring 330 while using 420-era syntax without the matching
// #extension line is accepted by real drivers, so CompileShader retries it at 460 instead of failing.
TEST_F(ProgramUtilTest, CompileShaderRetriesAt460WhenLegacyVersionRejects420Syntax) {
// used to be forced to. A legacy shader using 420-era syntax without the matching #extension line
// is accepted by real drivers, so CompileShader retries the normalized source at 460 rather than
// failing. Only MobileGL's own normalization is rescued this way - an application-declared
// "#version 330" keeps strict 3.30 semantics, which is what the CTS negative-compile cases need.
TEST_F(ProgramUtilTest, CompileShaderRetriesAt460WhenNormalizedLegacyVersionRejects420Syntax) {
using namespace MG_Util::ShaderTranspiler;
String source = R"(#version 330
String source = R"(#version 130
layout(binding = 0) uniform sampler2D InSampler;
in vec2 texCoord;
out vec4 fragColor;
varying vec2 texCoord;
void main() {
fragColor = texture(InSampler, texCoord);
gl_FragColor = texture2D(InSampler, texCoord);
})";
PreprocessShaderSource(ShaderStage::Fragment, source);
// The normal path still emits 330 - the retry must not become the default.
@@ -952,10 +957,21 @@ void main() {
TEST_F(ProgramUtilTest, RetargetLegacyVersionDirectiveOnlyTouchesNormalizedDesktopCore) {
using namespace MG_Util::ShaderTranspiler;
String normalized = "#version 330 core\nvoid main() {}\n";
// Only MobileGL's own normalization is retargetable, and it is recognised by the marker the
// preprocessor leaves on the directive line - so normalize a legacy source rather than
// hand-writing the directive the marker belongs to.
String normalized = "#version 130\nvoid main() {}\n";
PreprocessShaderSource(ShaderStage::Vertex, normalized);
ASSERT_EQ(normalized.find("#version 330 core "), 0u);
EXPECT_TRUE(RetargetLegacyVersionDirectiveTo460(normalized));
EXPECT_EQ(normalized.find("#version 460 core"), 0u);
// An application that declared 330 itself keeps strict 3.30 semantics: raising it would
// re-legalize the CTS negative-compile cases.
String declared330 = "#version 330 core\nvoid main() {}\n";
EXPECT_FALSE(RetargetLegacyVersionDirectiveTo460(declared330));
EXPECT_EQ(declared330.find("#version 330 core"), 0u);
// Already modern: nothing to retarget.
String modern = "#version 460 core\nvoid main() {}\n";
EXPECT_FALSE(RetargetLegacyVersionDirectiveTo460(modern));
+9 -6
View File
@@ -197,13 +197,15 @@ TEST(DirectGLESSanity, AdvertisesDepthTextureForGlmarkShadowScenes) {
EXPECT_NE(std::find(extensions.begin(), extensions.end(), MobileGL::E_GL_ARB_depth_texture), extensions.end());
}
TEST(DirectGLESSanity, AdvertisesVoxyRequiredRenderingExtensionsAtExperimentalCTSVersion) {
// The advertised target went back to 3.3 (see "restore target GL version to 3.3"); Voxy only ever
// needed the extensions, which stay advertised, so assert what the backend really reports.
TEST(DirectGLESSanity, AdvertisesVoxyRequiredRenderingExtensions) {
MobileGL::MG_Backend::DirectGLES::BackendObject_DirectGLES backend;
const auto& rendererInfo = backend.GetRendererInfo().RendererGLInfo;
const auto& extensions = rendererInfo.Extensions;
EXPECT_EQ(rendererInfo.TargetGLVersion.Major, 4);
EXPECT_EQ(rendererInfo.TargetGLVersion.Minor, 6);
EXPECT_EQ(rendererInfo.TargetGLVersion.Major, 3);
EXPECT_EQ(rendererInfo.TargetGLVersion.Minor, 3);
EXPECT_EQ(rendererInfo.TargetGLVersion.Patch, 0);
EXPECT_NE(std::find(extensions.begin(), extensions.end(), MobileGL::E_GL_ARB_compute_shader),
@@ -397,13 +399,14 @@ TEST(DirectVulkanSanity, RenderPassExtentUsesSwapchainSizeOnlyForDefaultFramebuf
MobileGL::IntVec2(512, 512));
}
TEST(DirectVulkanSanity, AdvertisesVoxyRequiredRenderingExtensionsAtExperimentalCTSVersion) {
// See the DirectGLES twin above: the target version is 3.3 again, the extensions are what matter.
TEST(DirectVulkanSanity, AdvertisesVoxyRequiredRenderingExtensions) {
MobileGL::MG_Backend::DirectVulkan::BackendObject_DirectVulkan backend;
const auto& rendererInfo = backend.GetRendererInfo().RendererGLInfo;
const auto& extensions = rendererInfo.Extensions;
EXPECT_EQ(rendererInfo.TargetGLVersion.Major, 4);
EXPECT_EQ(rendererInfo.TargetGLVersion.Minor, 6);
EXPECT_EQ(rendererInfo.TargetGLVersion.Major, 3);
EXPECT_EQ(rendererInfo.TargetGLVersion.Minor, 3);
EXPECT_EQ(rendererInfo.TargetGLVersion.Patch, 0);
EXPECT_NE(std::find(extensions.begin(), extensions.end(), MobileGL::E_GL_ARB_compute_shader),
+5 -3
View File
@@ -1867,11 +1867,13 @@ TEST_F(TextureTest, DirectGLESTreats2DArrayAsSupportedTextureTarget) {
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture2DArray));
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture3D));
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture2D));
// 1D and 1D-array are emulated as 2D / 2D-array (MapToBackendTextureTarget), matching
// SPIRV-Cross's ES 1D-as-2D shader emission; only rectangle textures stay unsupported.
// Every desktop-only target is stored on an ES one (MapToBackendTextureTarget): 1D and
// 1D-array as 2D / 2D-array, matching SPIRV-Cross's ES 1D-as-2D shader emission, and
// rectangle as a plain 2D - it is single-level and already clamps, so only the
// non-normalized coordinates differ and LowerRectImagesForEssl handles those.
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture1D));
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::Texture1DArray));
EXPECT_FALSE(IsSupportedTextureTarget(TextureTarget::TextureRectangle));
EXPECT_TRUE(IsSupportedTextureTarget(TextureTarget::TextureRectangle));
}
// 2D-array textures keep their layer count constant across mip levels (GL 3.3 §3.9);