mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_Util, MG_Test): enable asynchronous shader compilation by default (P1 stage 7)
kAsyncShaderCompileDefault flips to true, which also advertises
GL_KHR_parallel_shader_compile by default on both backends. Unset
MOBILEGL_ASYNC_SHADER_COMPILE now resolves to ON; =0 remains the complete kill
switch (reverts the threading and withdraws the extension together).
The gate behind the flip (headless Mesa - llvmpipe for Espryt, lavapipe for
Magma - at c6299f75): GL30/31/32/33/40 mustpass plus the
KHR-GL46.parallel_shader_compile group, both backends, async=1 with the
extension advertised. 58,344 case-runs, 8 failures - and every one of the 8
also fails standalone at async=0, in the full async=0 suite arms with an
identical per-case failure set, and under the pre-P1-stage-6 library. Zero
async-attributable deltas; the 8 are Mesa-upgrade drift (4 unique signatures:
Espryt GL40 transform_feedback.draw_xfb{,_feedbackk}_test, Magma
texture_size_promotion.functional + packed_pixels rgb9_e5_format_red on
GL32/33/40), recorded for separate follow-up.
Validation under the flipped default (no env var): 553/553 unit at the default
AND with the kill switch; parallel_shader_compile 3/3 on both backends proving
the default advertises; 44+44 integration scenarios; 71/72 CI trace-replay
fixtures (the one failure is the pre-existing create-indirect lavapipe crash,
identical under the pre-fix library). The lifecycle test's contract updates
with the default: AsyncIsOnByDefaultAndTheOverrideDecidesEitherWay.
Not covered by this gate and deliberately left open: SSO/DSA suites (GL41+,
separate follow-up per review), and real-driver confirmation on NVIDIA/Mali -
the Mali-G77 on-device sweep runs separately as a report-only pass.
This commit is contained in:
@@ -135,16 +135,18 @@ TEST(ShaderCompilePoolLifecycle, DetectedThreadCountIsPositive) {
|
||||
EXPECT_GE(DetectShaderCompileThreadCount(), 1u);
|
||||
}
|
||||
|
||||
TEST(ShaderCompilePoolLifecycle, AsyncIsOffByDefaultAndTheOverrideDecidesEitherWay) {
|
||||
// The shipped default is still off, and an unset MOBILEGL_ASYNC_SHADER_COMPILE resolves
|
||||
// to it. If the first expectation ever fails without the constant having been
|
||||
// deliberately flipped, something enabled async by accident.
|
||||
TEST(ShaderCompilePoolLifecycle, AsyncIsOnByDefaultAndTheOverrideDecidesEitherWay) {
|
||||
// The shipped default flipped to ON at stage 7 (the GL30-40 + parallel_shader_compile
|
||||
// gate found zero async-attributable failures), and an unset
|
||||
// MOBILEGL_ASYNC_SHADER_COMPILE resolves to it. If the first expectation ever fails
|
||||
// without the constant having been deliberately flipped back, something disabled async
|
||||
// by accident - the kill switch below is the supported way off.
|
||||
//
|
||||
// Driven through Features rather than read from it: from stage 3 on, the whole suite is
|
||||
// also run with MOBILEGL_ASYNC_SHADER_COMPILE=1 exported, so a test that simply asserted
|
||||
// "the resolved answer is false" would either fail there or - worse - silently pass in a
|
||||
// Driven through Features rather than read from it: the suite is also run with
|
||||
// MOBILEGL_ASYNC_SHADER_COMPILE exported both ways, so a test that simply asserted
|
||||
// the resolved answer would fail in one of those runs or - worse - silently pass in a
|
||||
// binary that never loaded the config and prove nothing at all.
|
||||
EXPECT_FALSE(kAsyncShaderCompileDefault);
|
||||
EXPECT_TRUE(kAsyncShaderCompileDefault);
|
||||
|
||||
const MG_Config::QuirkOverride saved = MG_Config::Features.AsyncShaderCompile;
|
||||
MG_Config::Features.AsyncShaderCompile = MG_Config::QuirkOverride::Auto;
|
||||
|
||||
@@ -18,13 +18,14 @@
|
||||
// time. Do not add one here.
|
||||
|
||||
namespace MobileGL::MG_Util::Async {
|
||||
// Stage 1 ships the whole machinery switched off: the pool is constructible and tested,
|
||||
// but nothing in the GL pipeline posts to it. The flip to true happens only after the
|
||||
// real-client soak in the final stage, because the riskiest part of asynchronous
|
||||
// compilation is not the joins - it is that Iris and Sodium change their submission
|
||||
// schedule the moment GL_KHR_parallel_shader_compile is advertised, and a recorded trace
|
||||
// can never cover that path.
|
||||
inline constexpr Bool kAsyncShaderCompileDefault = false;
|
||||
// Stage 7: on by default. The gate behind the flip (2026-08-09, headless Mesa, both
|
||||
// backends): GL30-40 mustpass + KHR-GL46.parallel_shader_compile at async=1 with the
|
||||
// extension advertised - 58,344 case-runs, 8 failures, and every one of the 8 also
|
||||
// fails standalone at async=0 and under the pre-P1 library, i.e. zero async-attributable
|
||||
// deltas. The risk this comment used to name - Iris and Sodium changing their submission
|
||||
// schedule the moment GL_KHR_parallel_shader_compile is advertised - remains the one
|
||||
// thing a recorded trace cannot cover, which is why the kill switch below stays.
|
||||
inline constexpr Bool kAsyncShaderCompileDefault = true;
|
||||
|
||||
// MOBILEGL_ASYNC_SHADER_COMPILE forces the answer either way; unset keeps the built-in
|
||||
// default above. Falsy is a complete kill switch: it reverts the threading *and*
|
||||
|
||||
Reference in New Issue
Block a user