Files
MobileGL/docs/archive/notes/p05/p05-results/program-artifacts-v1.md
T

13 KiB

p05-program-artifacts — results v1

Tree ~/w7/p05-program-artifacts, branch p05/program-artifacts, base feat/disaggregated @ 6672778b. Build: build-linux/ Release, /usr/sbin/clang++ (clang 22), ccache (CCACHE_BASEDIR=/home/swung/w7), libstdc++ (__GLIBCXX__ 20260625), MOBILEGL_BUILD_TEST=ON, MOBILEGL_BUILD_INTEGRATION_TEST=ON. Not pushed. ~/w7/pipe untouched (only read: ctest -N, nm, and a direct run of one existing test binary for the A/B below).

Commits (oldest first)

hash subject
a180dc57 [Refactor] (Program): extract ProgramArtifacts.h - move TypeFacts, ResourceReflection, XfbVarying, LinkArtifacts and SpirvArtifacts to namespace scope with in-class aliases so every existing spelling compiles unchanged; pure move
3ce1264c [Refactor] (Program): stop ProgramObject.h including SpvcSession.h - it names no spirv-cross or SPIRV-Reflect symbol
77beb7d6 [Feat] (Program): add the reflection-archive field tables and sizeof trip wires to ProgramArtifacts.h

Files touched (vs 6672778b): MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h (new, 576 lines), MobileGL/MG_State/GLState/ProgramState/ProgramObject.h (-386/+15), MobileGL/MG_Test/Program/ProgramArtifactsTest.cpp (new), MobileGL/MG_Test/Program/CMakeLists.txt (+21). Nothing else — commit 2 needed no consumer include additions (all 8 includers + ProgramObject.cpp built without SpvcSession.h forwarded).

What landed (B.2 checklist)

  • ProgramArtifacts.h: banner copied from ProgramObject.h; includes exactly <Includes.h> and <set>; PURITY comment; namespace MobileGL::MG_State::GLState { inline constexpr Uint kInvalidUniformOffset = ~0u; TypeFacts; ResourceReflection; the 4 using reflections; XfbVarying; LinkArtifacts (+ its comment block, with the one added I5 sentence); SpirvArtifacts (+ comment block); VisitFields x5; trip wires }. Struct bodies moved verbatim (re-indented one level), no field added/removed/reordered/re-typed; program and uniformInitialValues keep their glslang types (D5).
  • ProgramObject.h: #include "ProgramArtifacts.h" after "ShaderObject.h"; old :41-104 replaced by the 9-line alias block (fully qualified RHS); kInvalidUniformOffset re-exported as static constexpr Uint kInvalidUniformOffset = MobileGL::MG_State::GLState::kInvalidUniformOffset; (comment kept); old :1144-1171 and :1173-1449 deleted; commit 2 drops #include <MG_Util/ShaderTranspiler/SpvcSession.h>. MAX_UNIFORM_LOCATIONS and the glslang:: accessors stay. m_artifacts/m_spirv private, Artifacts()/Spirv() untouched (I5).
  • VisitFields: free constrained templates (requires std::same_as<std::remove_const_t<Self>, T>), contract v(const char*, Field&), tables never recurse; counts TypeFacts 20, ResourceReflection 14 (type as a value), XfbVarying 11, LinkArtifacts 57 (every member except program), SpirvArtifacts 8.
  • Trip wires: static_assert(is_trivially_copyable_v<TypeFacts> && sizeof(TypeFacts) == 44); under #if defined(__GLIBCXX__) && !defined(_GLIBCXX_DEBUG) && (SIZE_MAX == UINT64_MAX): MGL_RESOURCEREFLECTION_SIZE 128, MGL_XFBVARYING_SIZE 128, MGL_LINKARTIFACTS_SIZE 1056, MGL_SPIRVARTIFACTS_SIZE 88 (measured on this build via == 1 notes); #elif defined(_LIBCPP_VERSION) && (SIZE_MAX == UINT64_MAX) && defined(MGL_ARTIFACT_SIZES_LIBCXX_PINNED) left inert for the integrator (C.4); the four static_asserts guarded by #ifdef MGL_LINKARTIFACTS_SIZE with the "add the field to VisitFields(...) then update this number" messages.
  • Tests (ProgramArtifacts.*, label unit, first include is the artifacts header): AliasesAreTheSameTypes (9 is_same_v static_asserts + kInvalidUniformOffset), TypeFactsIsPodOf44Bytes, VisitFieldsCoversEveryMember (20/14/11/57/8, const == non-const, names distinct), VisitFieldsPassesConstnessThrough (extra: const walk yields const refs, mutable walk writes through), SizesArePinnedOnThisToolchain (EXPECT_EQ under the same #if, RecordProperty("sizeof_*") x5 always, plus a printf line sizeof: TypeFacts=44 ResourceReflection=128 XfbVarying=128 LinkArtifacts=1056 SpirvArtifacts=88).

Verification — every command and its actual result

All run in WSL Arch, cwd ~/w7/p05-program-artifacts, after commit 3 (77beb7d6) unless stated.

# command result
1 cmake --build build-linux -j 16 (after each commit) commit 1: OK (186 steps, whole ProgramObject.h fan-out); commit 2: OK (183 steps, zero consumer edits needed); commit 3: OK; post-commit re-run: ninja: no work to do. Logs ~/w7/pa-build{1,2,3}.log
2 ctest --test-dir build-linux -L unit --no-tests=error -j 8 100% tests passed, 0 tests failed out of 1463 (3 ***Skipped: LogLevel.DebugBuildKeepsEverything, LogLevel.AssertIsLiveInDebugBuilds, XfbFrontendOrderInvarianceTest.DumpBSpirvForDisassembly — skip by design). Log ~/w7/pa-unit3.log. (After commit 1 alone: 1460/1460.)
3 ctest --test-dir build-linux -L integration-gpu --no-tests=error -j 8 99% tests passed, 5 tests failed out of 868: the four *IsActuallyArmedWhenTheEnvironmentPinsItOn* (DirectGLES UnlocatedIoBlocks, DirectVulkan PrimGenReroute, DirectGLES + DirectVulkan PointSizeDemotion) — the known -j flake — and DirectVulkan.IterationRPProgram203Scenario.FixedCompleteInputProducesFixedCompleteGoldenOutput. Log ~/w7/pa-igpu3.log
4 ctest --test-dir build-linux -L integration-gpu --rerun-failed -j 1 80% tests passed, 1 tests failed out of 5: the four flake lanes pass; DirectVulkan.IterationRPProgram203Scenario.FixedCompleteInputProducesFixedCompleteGoldenOutput still fails (IterationRPProgram203Scenario.cpp:371,377, golden half-float texel mismatch, mismatchTexels 1 vs 0). Log ~/w7/pa-igpu3-rerun.log
5 A/B of #4's failure on the UNTOUCHED base binaries: MOBILEGL_BACKEND_TYPE=DirectVulkan __EGL_VENDOR_LIBRARY_FILENAMES=/usr/share/glvnd/egl_vendor.d/50_mesa.json ~/w7/pipe/build-linux/MobileGL/MG_IntegrationTest/MobileGLIntegrationTest --gtest_filter=IterationRPProgram203Scenario.FixedCompleteInputProducesFixedCompleteGoldenOutput --gtest_also_run_disabled_tests (cwd = that binary's MG_IntegrationTest dir; the env is what the ctest ENVIRONMENT property injects) x3, and the same for my binary x3 base (built 22:06 at 6672778b): FAILED 3/3; mine: FAILED 3/3. Pre-existing on this WSL/lavapipe machine, independent of this package (the package touches no code path — only type scope — and the library .text is byte-identical, see #13). Its DirectGLES twin is ***Skipped on both.
6 ctest -N name diff: ctest --test-dir build-linux -N | grep -E '^\s+Test\s+#' | sed 's/^ *Test *#[0-9]*: //' | sort vs the same on ~/w7/pipe/build-linux; comm -23 before after before 2326, after 2331; comm -23 empty; comm -13 = exactly the 5 new ProgramArtifacts.* names. NOTE: the brief's pattern '^\s+Test #' (single space) only matches test numbers >= 1000 (ctest right-aligns: Test #984: vs Test #1234:); with it the diff is garbage (two spurious QueryTest.* "additions", my tests invisible). Use '^\s+Test\s+#'.
7 ctest --test-dir build-linux -L unit -N | grep -c ProgramArtifacts 5 (the label reaches ctest -L unit)
8 ODR: grep -rn "^\s*struct \(TypeFacts|ResourceReflection|XfbVarying|LinkArtifacts|SpirvArtifacts\)\b" MobileGL exactly 5 hits, all in ProgramArtifacts.h (lines 31, 63, 95, 160, 359)
9 grep -n "#include" MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h 2 lines: <Includes.h> (line 10), <set> (line 15)
10 grep -c "glslang::" MobileGL/MG_State/GLState/ProgramState/ProgramArtifacts.h 2 (lines 165 SharedPtr<glslang::TProgram> program; and 232 Vector<glslang::TIntermediate::TUniformInitializer> uniformInitialValues;)
11 Closure probe: printf '#include <MG_State/GLState/ProgramState/ProgramArtifacts.h>\n' > /tmp/probe_pa.cpp; clang++ -std=gnu++23 -Iinclude -IMobileGL -IMobileGL/MG_Pipe -I3rdparty/xxHash -I3rdparty/Vulkan-Headers/include -H -E -o /dev/null /tmp/probe_pa.cpp 2>&1 | grep -E '^\.+ ' | grep -E 'ShaderObject.h|SpvcSession.h|MG_Util/ShaderTranspiler/|MobileGL/Config.h|MobileGL/MG_Backend/|BufferState/' empty (0 forbidden of 653 closure lines). The only MobileGL/ headers in the closure: Defines.h, Includes.h, ProgramArtifacts.h, MG_Util/Debug/Log.h, MG_Util/GLExtensions.h, MG_Util/PlatformStubs.h, MG_Util/Types.h.
12 clang++ ... -fsyntax-only /tmp/probe_pa.cpp OK (header self-contained; ProgramArtifactsTest.cpp includes it first as the in-tree proof)
13 git diff --stat 6672778b -- MobileGL/MG_Backend MobileGL/MG_Impl empty (also after commit 2 — no include-line additions were needed)
14 Symbol attribution (no scripts/symbol_report.py in this tree — done by hand with nm --defined-only -S + c++filt + size --format=sysv, script scratchpad/wf3/p05-program-artifacts/symcmp.py; normalisation folds GLState::ProgramObject::{TypeFacts,ResourceReflection,XfbVarying,LinkArtifacts,SpirvArtifacts} -> GLState::X on both sides, multiset compare on (name, type, size)); before = ~/w7/pipe/build-linux/libMobileGL.so (6672778b, 22:06), after = build-linux/libMobileGL.so symbol-report: .text 10792579 -> 10792579 (byte-identical); 30511 -> 30511 defined symbols: 0 added, 0 removed, 1 resized, 43 renamed; identical after commit 1 alone (~/w7/pa-sym1.txt) and after commit 3 (~/w7/pa-sym3.txt). The 1 "resized" is r [122] -> [107] typeinfo name for std::_Sp_counted_ptr_inplace<...LinkArtifacts, allocator<void>, _Lock_policy 2> — the RTTI name string (rodata, not code), 15 bytes shorter because 13ProgramObject left the mangled name. Fully attributed; commits 2 and 3 add no symbol (VisitFields is uninstantiated outside the test binary).
15 Red-for-its-reason (scratch copy of the header under /tmp/pa-neg, tree untouched): add Int addedWithoutATableEntry = 0; to LinkArtifacts, clang++ -I/tmp/pa-neg ... -fsyntax-only /tmp/probe_pa.cpp exit 1: error: static assertion failed ... 'sizeof(LinkArtifacts) == 1056': LinkArtifacts changed size: add the field to VisitFields(LinkArtifacts) ..., then update this number / note: expression evaluates to '1064 == 1056'
16 git status --short (excluding build-linux/) after each commit clean
17 Line endings: grep -c $'\r' on the two headers and the test 0 / 0 / 0

Deviations from the brief (with reasons)

  1. Comment respellings in the moved text (commit 1). Five comment lines that moved verbatim spell glslang::TType, glslang::TLayoutMatrix, glslang::TBasicType, glslang::TObjectReflection, glslang::TProgram; with them the header had 8 glslang:: lines, and the gate/D5 pins the count at exactly 2. Respelled comment-only as glslang TType etc. (no code token changed). The brief's "verbatim" and "exactly 2" cannot both hold literally; the gate wins (ROADMAP.md:7).
  2. LinkArtifacts field count is 57 of 58, not 52 of 53. Counted mechanically from the moved source (program + 57 others; a lines-ending-in-; count under-reads because several members carry trailing comments). VisitFieldsCoversEveryMember expects 57. The brief's 53 is a stale scout number.
  3. ctest -N grep pattern corrected to '^\s+Test\s+#' (see #6) — the brief's pattern silently drops tests numbered < 1000.
  4. One extra test VisitFieldsPassesConstnessThrough (adds only; brief allows additions) — pins that the single table really serves both directions.
  5. MobileGL/MG_Test/Program/CMakeLists.txt stanza appended at the end of the file (after the existing gtest_discover_tests block) rather than "copied next to" AsyncCompileTest; content is the AsyncCompileTest shape with DISCOVERY_TIMEOUT 30 PROPERTIES LABELS unit as specified.
  6. scripts/symbol_report.py absent in this tree (owned by p05-include-gate); the by-hand equivalent above records the numbers. The brief's --strip-scope 'MobileGL::MG_State::GLState::ProgramObject::' as a plain textual strip is NOT the right normalisation (it leaves a bare LinkArtifacts on the before side versus MobileGL::MG_State::GLState::LinkArtifacts on the after side and reports 43 added / 43 removed); the integrator's run of the real script should fold GLState::ProgramObject::X -> GLState::X (or strip only ProgramObject::). Flagging so C.4 does not read a false 43/43.

Notes for the integrator

  • libc++ branch of the trip wires is inert until MGL_ARTIFACT_SIZES_LIBCXX_PINNED is defined with the NDK numbers (C.4); ProgramArtifacts.SizesArePinnedOnThisToolchain prints and RecordPropertys all five sizes on every platform for that purpose.
  • The glibc++ guard is exactly the brief's (__GLIBCXX__ && !_GLIBCXX_DEBUG && SIZE_MAX == UINT64_MAX); it does not exclude _GLIBCXX_USE_CXX11_ABI=0 (COW std::string, 8 bytes) — no MobileGL toolchain uses that, mentioned only for completeness.
  • DirectVulkan.IterationRPProgram203Scenario.FixedCompleteInputProducesFixedCompleteGoldenOutput is red on this WSL machine at the base commit (#5) — expect it in the integrator's baseline too.

Unfinished

Nothing in scope. Not done by design/ownership: libc++ size pin (integrator, C.4); scripts/check_include_closure.py --probe artifacts-header run (script lives in p05/include-gate; the manual -H probe #11 is its equivalent); narrowing ProgramTranslationCache.h/ProgramInterface.cpp to the new header and the UniformInitializer re-typing (P7 follow-ups per the brief).