mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-07 19:58:32 +09:00
[Test] (ShaderTranspiler): pin the two capture holes the side-by-side corpus run found
This commit is contained in:
@@ -415,6 +415,68 @@ void main() { gl_Position = tint; }
|
||||
}
|
||||
}
|
||||
|
||||
// AN OPAQUE uniform's explicit location must land in the same map as a plain one's, even
|
||||
// though it is the one kind the relaxed remap never touches and reflection could therefore
|
||||
// answer for. Found by running the retired scanner beside this capture over the whole corpus:
|
||||
// the scanner recorded these (it did not read types at all) and the first cut of the capture
|
||||
// did not, which would have demoted a declared location to an implementation-chosen one.
|
||||
//
|
||||
// The difference is not cosmetic. DoReflection marks everything in this map SOURCE-EXPLICIT,
|
||||
// which is what makes a collision a LINK ERROR under ARB_explicit_uniform_location; a location
|
||||
// arriving only through glslang's own layoutLocation() is treated as glslang's choice and
|
||||
// quietly moved out of the way instead.
|
||||
TEST_F(GlslangCaptureProbeTest, AnOpaqueUniformsExplicitLocationIsCapturedAlongsideAPlainOnes) {
|
||||
const String source = R"(#version 460 core
|
||||
layout(location = 7) uniform sampler2D uTex;
|
||||
layout(location = 11) uniform mat4 uMvp;
|
||||
layout(location = 20) uniform sampler2D uTexArray[3];
|
||||
out vec4 fragColor;
|
||||
void main() { fragColor = texture(uTex, uMvp[0].xy) + texture(uTexArray[1], vec2(0)); }
|
||||
)";
|
||||
|
||||
ShaderAttrib shaderAttrib{.shaderType = GL_FRAGMENT_SHADER, .sourceStr = source};
|
||||
auto shaderResult = ShaderCompiler::CompileShader(shaderAttrib);
|
||||
ASSERT_TRUE(shaderResult) << shaderResult.error().log;
|
||||
const UnorderedMap<String, Int> locations = CollectExplicitUniformLocations(*shaderResult.value());
|
||||
|
||||
ASSERT_EQ(locations.count("uTex"), 1u) << "the opaque half of the capture is missing";
|
||||
EXPECT_EQ(locations.at("uTex"), 7);
|
||||
ASSERT_EQ(locations.count("uMvp"), 1u) << "the snapshot half of the capture is missing";
|
||||
EXPECT_EQ(locations.at("uMvp"), 11);
|
||||
// Keyed by DECLARED name, which is what the reflection lookup reaches by stripping "[0]".
|
||||
ASSERT_EQ(locations.count("uTexArray"), 1u);
|
||||
EXPECT_EQ(locations.at("uTexArray"), 20);
|
||||
}
|
||||
|
||||
// GLSLANG'S SYNTHESIZED ATOMIC-COUNTER BLOCKS ARE NOT UNQUALIFIED STORAGE BLOCKS, however much
|
||||
// they look like one at the collect callback: relaxed parsing folds every atomic_uint into a
|
||||
// "gl_AtomicCounterBlock_<GL binding>" buffer block and leaves it unbound, because MobileGL
|
||||
// asks for auto-mapped bindings. Seeding one to GL binding 0 would overwrite the counter
|
||||
// buffer's real binding - which is the trailing number in that very name.
|
||||
//
|
||||
// Also found by the side-by-side corpus run: the retired scanner could not see these blocks at
|
||||
// all (they do not exist in the source), so the capture inherited a whole class of entries its
|
||||
// consumer was never written for.
|
||||
TEST_F(GlslangCaptureProbeTest, TheSynthesizedAtomicCounterBlocksAreNotCapturedAsStorageBlocks) {
|
||||
const String source = R"(#version 430 core
|
||||
layout(local_size_x = 1) in;
|
||||
layout(binding = 0) uniform atomic_uint counterA;
|
||||
layout(binding = 2) uniform atomic_uint counterB;
|
||||
layout(std430) buffer RealBlock { uint u; } realBlock;
|
||||
void main() { realBlock.u = atomicCounterIncrement(counterA) + atomicCounterIncrement(counterB); }
|
||||
)";
|
||||
|
||||
const LinkCapture capture = CaptureFromCompute(source);
|
||||
ASSERT_TRUE(capture.linked) << capture.log;
|
||||
|
||||
EXPECT_EQ(capture.storageBlocksWithoutBinding.count("RealBlock"), 1u)
|
||||
<< "the application's own unqualified block is still recognised";
|
||||
for (const String& name : capture.storageBlocksWithoutBinding) {
|
||||
EXPECT_FALSE(name.starts_with(MG_Util::ShaderTranspiler::ATOMIC_COUNTER_BLOCK_PREFIX))
|
||||
<< "a synthesized atomic-counter block reached the storage-block capture: " << name;
|
||||
}
|
||||
}
|
||||
|
||||
// KHR-GL43.explicit_uniform_location: layout(binding = 0x2) on a sampler is its initial texture
|
||||
// unit. Same scenario the lexical extractor carried, now answered by the IO resolver - which
|
||||
// gets the C-style literal rules for free, and sees a binding no scanner could have read.
|
||||
|
||||
Reference in New Issue
Block a user