- ID-132's finding, diagnosed: with the flip thrown the 70 red lane entries are ONE race
and two debts. The race is the client's residual fill writing gPipeInputs while the apply
thread is inside an earlier UNBARRIERED record. Measured interleaving, verbatim:
`[MobileGLIntegra/ERROR] RA2-PROBE fill verb=DrawElements wireop=81 waitclass=-1
applierInside=1` then `[mgl-srv-apply/ERROR] RA2-PROBE unfresh field=IsCapabilityEnabled
verb=DrawElements serverStamped=0 ownership=RECORD-SUPPLIED` then
`[mgl-srv-apply/FATAL] MGPipe: Fatal{UnmigratedPipeInput, "IsCapabilityEnabled@DrawElements"}`.
The GL thread's MGPipeServerClearVerbBoundary withdrew the applier's own stamp mid-record.
- The marker's verb is the CLIENT's verb, which is what identifies the writer without a
probe at all: the applier can only ever put a verb of MGP_VERB_OP_LIST into the block, and
40 of the 54 unbracketed aborts named a verb that is not in it.
- A/B control on the same binary and the same records: MOBILEGL_IPC_RUN_AHEAD=0 is 8/8 green
where the default arm is 2/6 red, so the defect is in the wait rule and not in a record.
- RefusePipeInputsTouchWhileApplierOwnsIt could not fire on any of it: its run-ahead arm read
`if (isBarrieredFill) return;`, and that sentence is a claim about the FUTURE ("this thread
is about to park behind the record"). The order at the validate point is fill, then emit,
then park. So the arm now tests the fact - `isBarrieredFill && !ApplyThreadIsInsideApplier()`
- and the fill sites MAKE it true first with §2.5's forced wait (QuiesceApplierBeforeFill).
- TWICE PER VERB, because the block is written in two phases that straddle publication: the
serial bump / stamp withdrawal / verb rename run before the fourteen emitters and the
63-field walk of step 4 runs after them, and the records those emitters published are
records whose apply reads the block.
- ClientVerbIsBarriered: MGP_VERB_OP_LIST joins the whole draw family through one row
(DrawVbo -> DrawArrays), so inverting it verb-first answered kOpCount for DrawElements and
eighteen other draw verbs, and the "unknown verb answers barriered" default filled for each
while the record it published was a kWaitNone draw_vbo it never parked behind. The family's
row is applied to the family; every other unknown verb keeps the conservative answer, which
the wait above now makes honest. Measured alone it is worth 112 -> 133 isplit; with the wait
in place the lane is 161 either way, so this half is the PERFORMANCE half - without it every
indexed draw takes a forced drain and run-ahead is lockstep by another name on the draw path.
- Red-once A: put the guard's arm back to `if (isBarrieredFill) return;` and
RemoteGuards.ClientBarrieredFillWhileTheApplierIsInsideUnderRunAheadIsFatalByName exits 0
instead of aborting (`Value of: DiedOfAbort(child) Actual: false`), while its green control
keeps passing. Red-once B: delete the kDraw fallback and
RemoteRunAhead.AnIndexedDrawVerbIsUnbarrieredAndTouchesPipeInputsNotAtAll dies of signal 6
with `Fatal{RoleViolation, "gPipeInputs"} - the GL thread touched gPipeInputs
(MGPipeValidateForVerb) on a RUN-AHEAD session in a barriered fill that did not first wait
for the applier to catch up`.
- Both new cases run in the ordinary unit lane with run-ahead armed by the fixture, which is
what ID-132(1) asks for: the strict lane runs under lockstep and cannot see this class.
- Gate on the flipped head: unit 2256/2256, isplit 161/181 (was 112), gpu 1339/1359 (was 1290),
gens rc=0, flavours rc=0. The remaining 20 are two named debts, not this race: 18 are
`GetBufferBindingSlot@DrawArrays [UNBARRIERED]` on the two indirect multi-draw tiers, whose
retiring phase is P8, and 2 are ID-82's own refusal of client vertex arrays.
- The arm is stated and not inferred (ID-81): WaitForApplyToCatchUp's first test is
`m_runAheadArmed && m_started`, which reduces to Transport != Monolith. Under lockstep,
under monolith and under MOBILEGL_IPC_RUN_AHEAD=0 every line added here is a call that
returns, so those arms are unchanged.
fff9d639 - the DirectVulkan resident-buffer ordering and coherent trace-copy fix for Minecraft 26.3-rc-3 - into feat/disaggregated
MobileGL
A desktop OpenGL implementation
MobileGL is a free and open-source project that implements a desktop OpenGL API. The goal is to provide a complete desktop OpenGL implementation with a state management layer and multi-backend support.
Note
Status: In development. Parts of the codebase are incomplete. Current short-term target: OpenGL 4.2 (Core Profile).
Project positioning
MobileGL is an implementation of a desktop OpenGL library. It aims to provide:
- Full OpenGL state management.
- A front-end that exposes OpenGL functions.
- Multiple independent backend implementations, where each backend targets a specific graphics API and remains fully isolated from others.
This project is intended as an implementation/translation layer.
Key components
The repository is organized into following top-level modules:
- MG_State — state tracking and management logic for Graphics APIs.
- MG_Impl — front-end implementations of Graphics APIs that interact with
MG_StateandMG_Backend. - MG_Backend — per-backend translation layer that maps front-end Graphics APIs' semantics and state into concrete backend API calls (e.g. OpenGL ES, Vulkan).
- MG_Util and other utility modules.
Third-party components
MobileGL reuses several open-source projects:
- SPIRV-Cross by KhronosGroup - Apache License 2.0: github
- glslang by KhronosGroup - Various Licenses: github
- DiligentCore by Diligent Graphics - Apache License 2.0: github
- flat_hash_map by Malte Skarupke - Boost Software License 1.0: github
Refer to each component's repository for exact license texts. Any bundled third-party code in this repository is included under the upstream project's license.
Compatibility & target
- Short-term target:
OpenGL 4.2 (Core Profile). - Current development focus:
- Performance improvement
MG_StateandMG_ImplforOpenGL 4.2 (Core Profile)Direct (Vulkan)backendDirect (OpenGL ES)backend
Build Instructions
We currently provide no releases and no precompiled binaries.
If you want to try the project right now, you’ll need to build it yourself:
-
Clone the repository:
git clone https://github.com/MobileGL-Dev/MobileGL.git -
Initialize and update all submodules recursively:
git submodule update --init --recursive -
Follow glslang’s own documentation for its required initiation.
-
Configure and build the project with CMake:
cmake -B build cmake --build buildor do it in a modern way:
cmake -S . -B build -G Ninja -DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++ cmake --build buildAlternatively, you can use platform-specific build commands as needed.
Build For macOS
On macOS, MobileGL can be built as a dylib that exposes the normal OpenGL/CGL/NSOpenGL entry points and routes them to the DirectVulkan backend. This is useful for running applications such as Minecraft through their stock GLFW/LWJGL OpenGL path while MobileGL is injected before context creation.
Prerequisites:
- macOS with Clang and Ninja.
- Vulkan loader and MoltenVK installed. With Homebrew, the MoltenVK ICD is commonly located at
/opt/homebrew/etc/vulkan/icd.d/MoltenVK_icd.json.
Configure and build:
cmake -S . -B build-macos-magma \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DMOBILEGL_BACKEND_TYPE=DirectVulkan \
-DMOBILEGL_BUILD_TEST=OFF \
-DMOBILEGL_BUILD_BENCHMARK=OFF
cmake --build build-macos-magma --target MobileGL -j8
The dylib will be generated at:
build-macos-magma/libMobileGL.dylib
To run Minecraft by MobileGL from a launcher like PrismLauncher, keep the stock LWJGL/GLFW natives and add a wrapper command to the instance settings:
env DYLD_INSERT_LIBRARIES=/absolute/path/to/MobileGL/build-macos-magma/libMobileGL.dylib MOBILEGL_BACKEND_TYPE=DirectVulkan VK_ICD_FILENAMES=/opt/homebrew/etc/vulkan/icd.d/MoltenVK_icd.json
Also make sure the JVM arguments include:
-XstartOnFirstThread
DYLD_INSERT_LIBRARIES must be active before GLFW creates its OpenGL context. After startup, the Minecraft F3 screen should report MobileGL and the Direct (Vulkan) backend if the injection worked.
Build Options
| Option | Description | Default |
|---|---|---|
MOBILEGL_BUILD_TEST |
Build MobileGL tests (requires Clang) | ON |
MOBILEGL_BUILD_BENCHMARK |
Build MobileGL benchmarks (requires Clang) | ON |
MOBILEGL_FORCE_RELEASE_OPT |
Enable O3 and LTO in Debug build | ON |
MOBILEGL_ENABLE_TRACY |
Enable Tracy profiler for performance analysis | OFF |
Notes:
- The project requires C++23.
MG_TestandMG_Benchmarkcan only be built with Clang, not GCC. To enforce Clang, add-DCMAKE_C_COMPILER=clang -DCMAKE_CXX_COMPILER=clang++to your command.- On Android, tests and benchmarks are always disabled.
Environment Variables
MobileGL supports runtime configuration via environment variables.
Supported Keys
| Variable | Description | Allowed Values | Default |
|---|---|---|---|
MOBILEGL_BACKEND_TYPE |
Select active backend implementation at startup. | DirectGLES, DirectVulkan |
DirectGLES |
MOBILEGL_DISABLE_TIMERQUERY |
Disable GPU timer-query exposure and use. | 0, 1 |
0 |
MOBILEGL_ESPRYT_USE_ANGLE |
Load ANGLE EGL/GLES libraries. | 0, 1 |
0 |
MOBILEGL_MAGMA_DISABLE_SUBGROUP |
Disable Vulkan shader subgroup support. | 0, 1 |
0 |
MOBILEGL_ADVERTISE_FP64 |
Advertise GL_ARB_gpu_shader_fp64. GLSL double/dvec/dmat compile and run either way - they are narrowed to 32 bits - so this only changes whether an application is told it has 64-bit precision, which it does not. |
0, 1 |
0 |
MOBILEGL_MAGMA_R11G11B10F_FALLBACK |
Use Magma's R11G11B10F format fallback. | 0, 1 |
0 |
MOBILEGL_MAGMA_FRAMESINFLIGHT |
Set Magma frames in flight. | Integer 1–64 |
3 |
MOBILEGL_ESPRYT_AVOID_SAMPLER_MIPMAP_MIN_FILTER |
Avoid sampler mipmap minification filters. | 0, 1 |
0 |
MOBILEGL_COHERENT_AS_FLUSH |
Treat persistent GL_MAP_FLUSH_EXPLICIT_BIT maps as coherent (app-compat for engines like Flywheel that never flush them). |
0, 1 |
0 |
MOBILEGL_ESPRYT_FORCE_DS_READBACK_EMULATION |
Always emulate depth/stencil glReadPixels/glGetTexImage by shader sampling on Espryt, instead of using the driver's own depth/stencil readback where it has one. |
0, 1 |
0 |
VK_ICD_FILENAMES |
Select the Vulkan ICD used by the Vulkan loader. | Path to an ICD JSON file | Loader default |
License
This project is distributed under GNU LGPL v3.0. See the LICENSE file in the repository for detailed information.