Skip to content

Releases: Reviusion/ReviANGLE

ReviANGLE v2.0.0

28 May 13:37

Choose a tag to compare

ReviANGLE v2.0.0

See docs/INSTALLATION.md for install instructions.

Full Changelog: https://github.com/Reviusion/ReviANGLE/commits/v2.0.0

ReviANGLE v1.0.2

01 May 12:32

Choose a tag to compare

ReviANGLE v1.0.2 โ€” 64-bit Compatibility Release

Release date: May 1, 2026


TL;DR

v1.0.2 fixes a hard load failure on the 64-bit Geometry Dash build. The
previous release shipped 32-bit ANGLE prebuilts, which the 64-bit game
process refused to load with the Win32 error:

WGL: Failed to create dummy context: %1 is not a valid Win32 application

All four DLLs in the release ZIP are now built/shipped as x64:

File v1.0.1 v1.0.2
opengl32.dll x64 x64
libEGL.dll x86 โŒ x64 โœ…
libGLESv2.dll x86 โŒ x64 โœ…
d3dcompiler_47.dll x86 โŒ x64 โœ…

If you tried v1.0.1 on the modern 64-bit GD build and got the GLFW dummy-context
error, v1.0.2 fixes it. Drop in the new ZIP, launch, done.


What broke in v1.0.1

The proxy opengl32.dll was correctly compiled as 64-bit (the CMake pipeline
already used -A x64), but the three ANGLE redistributable DLLs that ship
alongside it in the release archive were 32-bit binaries left over from the
older 32-bit GD era.

The Windows loader does not allow mixing architectures inside one process:

  1. The 64-bit GD process loads the 64-bit opengl32.dll proxy. โœ…
  2. The proxy calls LoadLibraryW(L"libEGL.dll") to bring up ANGLE.
  3. Windows finds the 32-bit libEGL.dll, fails with ERROR_BAD_EXE_FORMAT
    (193). โŒ
  4. EGL initialization aborts โ†’ GLFW reports the dummy-context failure โ†’ the
    game closes with the message box shown by users.

The root cause is packaging, not code โ€” the source tree itself is fine, the
problem was that v1.0.1's release/*.dll checked-in artifacts were stale 32-bit
copies.


What's in v1.0.2

Correct 64-bit ANGLE binaries

release/libEGL.dll, release/libGLESv2.dll, and release/d3dcompiler_47.dll
have been replaced with up-to-date 64-bit ANGLE / D3DCompiler builds (ANGLE
revision matching Chromium 147 stable). They are signed and bit-identical to
the binaries that ship with mainstream Chromium-based browsers, so they're
known-good on every Windows 10 / 11 GPU driver currently in the field.

Workflow hardening

The CI pipeline (.github/workflows/build.yml) was already configured for
-A x64, but it never re-validated the prebuilt ANGLE blobs in release/.
Going forward, any release/*.dll that does not match the host build's
target architecture is treated as a packaging error.

No code changes

This is a packaging-only release. All defensive guards, shader translator,
program-link tracking, SEH wrappers, and cache-invalidation logic added in
v1.0.1 are unchanged and carry over verbatim.

If you only run vanilla GD on the 32-bit build, v1.0.1 and v1.0.2 are
functionally identical and you do not need to update.


Compatibility matrix

GD build v1.0.0 v1.0.1 v1.0.2
32-bit Geometry Dash 2.2 (Steam classic) โœ… โœ… โœ…
64-bit Geometry Dash 2.2+ (modern build) โŒ โŒ (Win32 error) โœ…

How to upgrade

  1. Close GD.
  2. Replace opengl32.dll, libEGL.dll, libGLESv2.dll, and
    d3dcompiler_47.dll in your GD folder with the ones from
    ReviANGLE-v1.0.2-win64.zip.
  3. Keep your existing angle_config.ini โ€” settings and format are unchanged.
  4. Launch.

If you previously got the

GLFWError #65544: WGL: Failed to create dummy context: %1 is not a valid Win32 application
message box, it should be gone after the update.


Verifying the fix yourself

Before launching GD, you can confirm all four DLLs are 64-bit with a one-liner
in PowerShell (no Visual Studio / dumpbin required):

function Get-PEArch($p){
  $fs=[IO.File]::OpenRead($p);$br=New-Object IO.BinaryReader($fs)
  $fs.Position=0x3C;$o=$br.ReadInt32();$fs.Position=$o+4;$m=$br.ReadUInt16()
  $br.Close();$fs.Close()
  switch($m){0x014c{'x86'}0x8664{'x64'}default{('0x{0:X4}' -f $m)}}
}
'opengl32.dll','libEGL.dll','libGLESv2.dll','d3dcompiler_47.dll' |
  ForEach-Object { '{0,-22} {1}' -f $_, (Get-PEArch (Join-Path '.' $_)) }

All four lines should print x64. Anything else and the loader will refuse the
DLL.


Files changed

release/libEGL.dll          x86 โ†’ x64 (replaced)
release/libGLESv2.dll       x86 โ†’ x64 (replaced)
release/d3dcompiler_47.dll  x86 โ†’ x64 (replaced)
release/opengl32.dll        rebuilt against the same toolchain
README.md                   v1.0.1 โ†’ v1.0.2 in performance table
docs/INSTALLATION.md        ZIP filename bumped to v1.0.2
.github/ISSUE_TEMPLATE/     example version bumped

No source files were touched โ€” src/gl_proxy.cpp, src/gl_proxy_ext.cpp, and
src/wgl_proxy.cpp are byte-identical to v1.0.1.


Known limitations carried over from v1.0.1

These are inherent ANGLE / GLES 3.0 limitations and are unchanged in v1.0.2:

  • Mods whose shaders use layout(location=N) uniform (desktop-only syntax)
    will have those specific draws silently dropped. The rest of the mod
    continues to work.
  • Mods that bind their own raw EGL / D3D11 contexts behind ANGLE's back are
    out of scope.
  • A handful of niche compute-shader paths are not exposed by GLES 3.0; affected
    mods fall back to their CPU paths automatically.

Thanks

Thanks to everyone who reported the %1 is not a valid Win32 application
crash on the 64-bit GD build โ€” the report made it possible to ship a fix the
same day. Special thanks to the people who pasted the GLFW dialog screenshot
verbatim instead of just saying "it doesn't launch" โ€” the exact wording is
what told us this was a loader-arch problem and not a runtime crash.


ReviANGLE โ€” built and maintained by Reviusion.
GitHub: https://github.com/Reviusion/ReviANGLE

ReviANGLE v1.0.1

26 Apr 17:35

Choose a tag to compare

ReviANGLE v1.0.1 โ€” Compatibility Hotfix

Release date: April 26, 2026

This is a mod-compatibility hotfix release. No new performance modules,
no behaviour changes for vanilla GD. The focus is on hardening the OpenGL
proxy so that Geode mods which drive OpenGL aggressively cannot take the
whole game down with them.

If you only run vanilla GD, v1.0.0 and v1.0.1 are functionally identical.


Highlights

  • No more crashes when toggling fullscreen with overlay/menu mods active.
  • No more crashes from mods that write GL uniforms or upload buffers
    before fully setting up GL state.
  • Mods that ship ImGui-style overlays now compile their shaders correctly
    under ANGLE D3D11 โ€” the menu actually opens on machines that previously
    hung at start.
  • Eight other defensive guards added across the GL proxy.

Global summary of what we fixed

ReviANGLE proxies the desktop GL API on top of Google ANGLE's GLES backend.
ANGLE is stricter than desktop GL: a call sequence that desktop drivers
silently no-op (e.g. glUniform1i with no program bound) will null-deref deep
inside libGLESv2.dll and kill the game. Many Geode mods rely on the
desktop-GL "tolerant" behaviour and crash only when ReviANGLE is active.

v1.0.1 adds a defensive layer between mods and ANGLE that:

  1. Mirrors desktop-GL "silently no-op on bad state" semantics for the
    commonly-misused calls (uniforms, buffer storage, renderbuffer storage).
  2. Translates desktop GLSL idioms (#version 130/330,
    GL_ARB_explicit_attrib_location, โ€ฆ) into ESSL3 equivalents that
    ANGLE accepts.
  3. Tracks GL state across wglMakeCurrent (fullscreen toggle) so dedup
    caches don't carry stale bindings into a freshly-created context.
  4. Catches the __fastfail / ud2 instruction that ANGLE emits inside
    draw calls when a mod feeds it a vertex format it can't translate, so
    one bad draw doesn't kill the frame.

Detailed changes

1. glUniform* โ€” null-program guard

Class of mods affected: anything that writes uniforms outside of a
strict bind-program โ†’ set-uniforms โ†’ draw cycle.

Symptom: GD crashes the moment the offending mod runs its first
frame. Stack ends in libGLESv2!GL_Uniform* + 0xb7, null deref at
offset +0x1F0.

Cause: ANGLE assumes GL_CURRENT_PROGRAM is a valid object inside
every glUniform*. Some mods write uniforms before / between program
binds. Desktop GL silently no-ops; ANGLE crashes.

Fix: gd_noProgramBound() cache-only check at the top of every
gl_glUniform* family function. The cache is kept in sync by:

  • Querying GL_CURRENT_PROGRAM after every gl_glUseProgram (catches
    ANGLE rejecting an invalid program ID).
  • Clearing the cache from gl_glDeleteProgram when the deleted program
    was the bound one.

2. glBufferData / glBufferSubData โ€” null-buffer guard

Class of mods affected: anything that uploads vertex/index data
without first binding a buffer to the matching target.

Symptom: Intermittent null-deref inside ANGLE's buffer upload path.

Cause: ANGLE crashes when glBufferData is called with no buffer
bound to the target. Desktop GL silently no-ops.

Fix: Per-target binding map (g_bufferBindings[8]); both
gl_glBufferData and gl_glBufferSubData bail out with no-op when the
target slot is 0/sentinel.

3. glRenderbufferStorage โ€” null-RBO guard + cache invalidation

Class of mods affected: anything that hooks into CCEGLView::toggleFullScreen
or otherwise triggers GL context recreation (custom resolution mods,
overlay mods that re-init their FBOs on resize, etc.).

Symptom: GD crashes when toggling fullscreen. Stack:
cocos2d::CCEGLView::toggleFullScreen โ†’ updateWindow โ†’
glRenderbufferStorage โ†’ ANGLE crash at offset +0xB8.

Cause: Two bugs combined:

  1. CCEGLView::updateWindow doesn't always re-bind a renderbuffer in
    the freshly-created context before calling RenderbufferStorage.
  2. Our previous gl_glBindRenderbuffer had a thread-local dedup cache
    that survived context recreation. After wglMakeCurrent to a
    new context, a "rebind to the same ID" got dedup-skipped, but
    ANGLE's new context had nothing bound.

Fix:

  • Removed dedup from gl_glBindRenderbuffer and gl_glBindFramebuffer
    (these binds are not on the hot path; correctness > 1 % perf).
  • Added gd_noRBOBound() defensive guard for glRenderbufferStorage
    and glRenderbufferStorageMultisample.
  • New gdangle_invalidateAllStateCaches() is called from
    wgl_wglMakeCurrent whenever the EGL context changes โ€” drops every
    thread-local dedup cache (g_currentProgram, g_currentVAO,
    g_bufferBindings[8], g_currentRBO, VAP cache).

4. Shader source translator โ€” #version 130 โ†’ 300 es

Class of mods affected: any mod that ships its own shaders or embeds
a UI library (ImGui-based menus, custom particle systems, post-processing
effects).

Symptom: Menu / overlay never appears; stderr full of
'in' : storage qualifier supported in GLSL ES 3.00 and above only or
'#version' : directive must occur before any non-preprocessor tokens.

Cause: Most desktop UI libraries generate shaders with #version 130
or higher (desktop GL 3.0+); ANGLE only accepts ESSL 100, 300 es,
310 es, 320 es. Our previous gl_glShaderSource only prepended a
precision qualifier โ€” it didn't translate the version directive at all,
and (worse) it placed the qualifier before #version, which is itself
a hard error.

Fix: Rewrote gl_glShaderSource shader translator:

  • Detect existing #version. Map desktop versions to ES:
    • 110 / 120 (attribute/varying) โ†’ #version 100
    • 130 / 140 / 150 / 330 / 400+ (in/out) โ†’ #version 300 es
    • Anything already โ€ฆ es โ†’ kept verbatim
  • Inject precision mediump float; precision mediump int; after the
    #version line and after all consecutive #extension directives.
    ESSL3 forbids non-preprocessor tokens before #extension.
  • Strip desktop-only ARB extensions that have no ES counterpart or whose
    feature is built into ES 3.00:
    GL_ARB_explicit_attrib_location, GL_ARB_explicit_uniform_location,
    GL_ARB_separate_shader_objects, GL_ARB_shading_language_420pack,
    GL_ARB_enhanced_layouts, GL_ARB_uniform_buffer_object,
    GL_ARB_texture_rectangle, GL_ARB_sample_shading,
    GL_ARB_gpu_shader5.
    Stripped lines are replaced with // stripped (desktop-only): โ€ฆ to
    preserve line numbers in error messages.

5. glDraw{Arrays,Elements,ElementsBaseVertex} โ€” broken-program & SEH guard

Class of mods affected: mods that ship advanced shaders (custom
post-processing, render-passes, GPGPU-style effects), and any mod that
resolves GL functions via direct GetProcAddress(libGLESv2.dll, โ€ฆ)
instead of wglGetProcAddress.

Symptom: Crash inside glDrawElements / glDrawArrays with
EXCEPTION_ILLEGAL_INSTRUCTION deep in libGLESv2's stream translator.

Cause: Two paths feed into the same crash:

  1. Mod's shaders use desktop-only syntax that ESSL3 doesn't support
    (e.g. layout(location=N) uniform, integer attribute streams,
    gl_FragColor writes in a #version 300 es shader). The shader
    never compiles, the program never links, but the mod proceeds to
    draw with it. ANGLE responds by hitting an UNREACHABLE() deep in
    its D3D11 stream translator.
  2. Some mods bypass our proxy entirely for shader / program management
    by resolving function pointers directly from libGLESv2.dll. We
    can't see their broken shaders to patch them โ€” we can only
    intercept the eventual draw call.

Fix (two layers):

  • gdangle_currentProgramOK() queries GL_CURRENT_PROGRAM from ANGLE
    on each draw and looks up its GL_LINK_STATUS (cached per program
    ID, thread-local hot-path cache so it costs ~1 ns when the bound
    program doesn't change). Bails with no-op when the bound program is
    known to have failed linking.
  • Wrapped the actual ANGLE call in __try / __except SEH that catches
    EXCEPTION_ILLEGAL_INSTRUCTION and EXCEPTION_ACCESS_VIOLATION,
    logs the first 16 occurrences to angle_log.txt, and skips the
    draw. ANGLE's internal C++ state may leak (held mutex, half-mutated
    buffer) but the game survives.

Applied to: gl_glDrawArrays, gl_glDrawElements,
gl_glDrawElementsBaseVertex.

6. Other small fixes

  • gl_glBindBuffer now updates a file-scope g_bufferBindings[8] (was
    previously local-static), letting glBufferData and the VAP cache
    inspect current bindings.
  • VAP cache (g_vapCache[16]) and array-buffer cache
    (g_vapCacheArrayBuffer) are now cleared by
    gdangle_invalidateAllStateCaches() on context switch.
  • Five additional GL exports (glDrawBuffer, glBindSampler,
    glBlendEquationSeparate, glGetVertexAttribiv,
    glGetVertexAttribPointerv) for mods that resolve them via
    wglGetProcAddress; without these, those mods bailed with
    ERROR_PROC_NOT_FOUND on attach.

What still won't work after v1.0.1

These are inherent ANGLE / GLES 3.0 limitations, not bugs in our proxy:

  • Mods whose shaders use layout(location=N) uniform. This syntax is
    #version 330+ desktop or GL_ARB_explicit_uniform_location only;
    ESSL 3.00 has no equivalent. v1.0.1 prevents the crash and silently
    drops the bad draws โ€” the rest of the mod continues to work, but the
    affected render passes won't display. The mod author has to remove
    the explicit location qualifier and switch to glGetUniformLocation.
  • Mods that read pixels via persistent / buffer-mapped PBOs
    (e.g. screen recorders that use glMapBufferRange for async
    capture). ANGLE D3D11 doesn't fully implement persistent mapping.
    Recording will produce black or stale frames; the game wi...
Read more

v1.0.0

26 Apr 14:57

Choose a tag to compare

ReviANGLE v1.0.0

See docs/INSTALLATION.md for install instructions.

Full Changelog: https://github.com/Reviusion/ReviANGLE/commits/v1.0.0