mirror of
https://github.com/MobileGL-Dev/MobileGL
synced 2026-09-08 04:08:32 +09:00
[Feat] (MG_State, MG_Util): async program linking on the job graph (P1 stage 4)
glLinkProgram with the flag on snapshots its inputs in a GL-thread prologue (stage-sorted shaders with their compile nodes taken without joining, env, explicit locations/fragdata/xfb, draw-buffer count), then runs the whole link body - glslang link/mapIO, SPIR-V, reflection, routing tables - as a ProgramLinkTask that auto-posts when its last compile dependency settles (+1-guarded countdown; no worker ever waits on another job). The publish is one move of the LinkArtifacts block at the join, with the second version bump so nothing memoized during the pending window survives. The consume-once TShader claim moved onto the shared compile node as a CAS: two link jobs racing for one shader resolve to winner-takes-the-parse, loser re-parses the preprocessed source against the node's own env - identical SPIR-V pinned by test for 2 and for 12 sharing programs. Two deliberate corrections to the design's cancel matrix, both test-proven: attach/detach do NOT cancel a pending link (the snapshot isolates it, and glCreateShaderProgramv's link-then-detach would otherwise discard its own result before anyone read it); and a compile node a pending link depends on is pinned against the orphan-name sweep - the ordinary LWJGL teardown compile/attach/link/detach/delete used to cancel the dependency and turn a must-pass link into GL_FALSE. Continuations are now throw-contained per-item (a stage-3 leftover made load-bearing by the first real continuation), and the review's deadlock find is fixed: the dispatch loop no longer cancels a node while holding the pool mutex, since that cancel can run OnDepSettled -> Post -> same mutex. Explicit joins: the draw path (GetProgramForDraw, both the pipeline stage loop and the plain-UseProgram half) and the composite-link site; destroy paths cancel-not-join; COMPLETION_STATUS readers stay non-joining. Gates: 506/506 unit both flag states; AsyncCompile/AsyncLink/AsyncTeardown suites x10 repeats clean both states (teardown with 128 jobs in flight, then re-Initialize); full NVIDIA DirectGLES retrace flag on twice - result sets identical to flag off, zero new deltas. Compile-phase prefix-diff, flag on vs off: complementary-reimagined 5.21s -> 2.16s, BSL 1.72s -> 0.90s - past the design's final acceptance targets before the KHR extension is even advertised. Default remains OFF until stage 5+7.
This commit is contained in:
@@ -2934,7 +2934,7 @@ TEST_F(ProgramTest, RecompileWithIdenticalSourceKeepsCompiledStateAndStillLinks)
|
||||
EXPECT_TRUE(ShaderHasMemoizedCompile(vs));
|
||||
|
||||
// A first link consumes the stored TShader; the redundant recompile below must not
|
||||
// disturb the preprocessed source that TakeShaderForLink re-parses from.
|
||||
// disturb the preprocessed source that ClaimParsedShader re-parses from.
|
||||
GLuint firstProgram = LinkVsFs(vs, fs, GL_TRUE);
|
||||
EXPECT_GE(GetUniformLocation(firstProgram, "uColor"), 0);
|
||||
|
||||
@@ -2959,7 +2959,7 @@ TEST_F(ProgramTest, RecompileWithIdenticalSourceKeepsCompiledStateAndStillLinks)
|
||||
EXPECT_EQ(String(sourceBuffer.data(), static_cast<size_t>(written)), String(kP0bVs));
|
||||
|
||||
// A second program built from the same, redundantly recompiled shaders links and
|
||||
// reflects - i.e. TakeShaderForLink's re-parse path survived the no-op.
|
||||
// reflects - i.e. ClaimParsedShader's re-parse path survived the no-op.
|
||||
GLuint secondProgram = LinkVsFs(vs, fs, GL_TRUE);
|
||||
EXPECT_GE(GetUniformLocation(secondProgram, "uColor"), 0);
|
||||
EXPECT_GE(GetUniformLocation(secondProgram, "uModel"), 0);
|
||||
|
||||
Reference in New Issue
Block a user