Repository navigation
Releases: metalsharp/WineMetalGL
Release list
WineMetalGL 3.7.0
WineMetalGL in arm64 Wine
WineMetalGL 3.7.0 runs inside a native arm64 Wine: CrossOver 27's arm64 bottles and MetalSharp's Wine with FEX (#13). It works for native ARM64 programs, x86_64 ones and 32-bit ones, on the arm64 core, with no Rosetta. Until now the Wine module was built for x86_64 Wine only, so in CrossOver 27 the forwarding opengl32.dll loaded but winemetalgl.dll didn't ("Failed to load module winemetalgl.dll", c0000135).
The arm64 Wine module
winemetalgl-3.7.0-arm64.tar.gzis a new package next to the x86_64 one, fromscripts/stage-release-arm64.sh:winemetalgl.dlland theopengl32.dllforwarder are ARM64X, so one DLL serves native ARM64 programs and x86_64 ones, which an arm64 Wine runs as ARM64EC.- An i386 build covers 32-bit programs through WoW64.
winemetalgl.soand the core are arm64.
- Fixes for the ARM64 half of an ARM64X DLL:
- The exception reporter reads an x64
CONTEXT, so it's now built for x86_64 and ARM64EC only, not for the native ARM64 half. - An arm64 Wine runs x86 code through its own emulator, not Rosetta, so the x87 sidecar hook is x86_64-host only. FEX's reduced-precision x87 mode is the counterpart.
- The exception reporter reads an x64
- Tested in MetalSharp Wine 2.0 (Wine 11.20 with FEX): OpenGL 4.6 WineMetalGL Core Profile in native ARM64 and x86_64 programs, with rendering checked by reading a pixel back.
The install scripts pick the right package
install-wine-module.shworks out whether the Wine is an x86_64 Wine or an arm64 one:- from the unix side it has (
lib/wine/x86_64-unixoraarch64-unix); - for a Wine with both, from the prefix's own
system32; WINEMETALGL_ARCHoverrides the detection.
- from the unix side it has (
install-crossover.shreads the bottle's ownsystem32/ntdll.dll(ARM64 in a CrossOver 27 arm64 bottle, x86_64 in an x86_64 one), so it works with or without CrossOver installed. An arm64 bottle gets:- the arm64 module in
~/Library/Application Support/WineMetalGL/lib/wine/{aarch64-windows,i386-windows,aarch64-unix}; - a
[Wine] DllPathdefault built onaarch64-windows; - the ARM64X
opengl32.dllandwinemetalgl.dllinsystem32, with the i386 ones insyswow64.
- the arm64 module in
- Either package installs into either kind of Wine: when a package isn't for the Wine it's given, the script downloads the matching one from the release (checked against
SHA256SUMS.txt). x86_64 Wine and bottles install exactly as before. - MetalSharp Wine:
- A folder of MetalSharp Wine gets its bundled WineMetalGL updated in place, with no prefix setup needed, since it's already the default OpenGL there.
- The signed
MetalSharp-Wine.appis left alone; it already uses WineMetalGL.
WineMetalGL 3.6.0
Minecraft / Performance / Installation Update
WineMetalGL 3.6.0 runs Minecraft: Java Edition natively on the arm64 core, faster than Apple's OpenGL, with shader packs. WineMetalGL Settings sets it up in Prism Launcher, the official launcher and Modrinth App, and installs into any Wine or CrossOver bottle on your Mac. This release also makes it easier to install and use WineMetalGL, and increases performance for several hard to fix pre-existing performance issues.
Games
- Minecraft: Java Edition, natively on the arm64 core, outside Wine (#68):
- A glue gives Minecraft an OpenGL 4.6 core context: SDL3 for 26.x, GLFW for 1.21.x. Sodium and Iris load as usual.
- BSL renders, at 82–84 fps against Apple's OpenGL's 60 (M4, 1708×960, uncapped). Seven of its shaders used names that are Metal or C++ keywords (a function named
vertex, a variable namednew), and its terrain rendered black. They are renamed now. - Sodium alone: 388 fps, against Apple's OpenGL's 153.
- Buffer copies keep the CPU's copy of the destination up to date. That removes two full waits for the GPU a frame, from Minecraft filling each new vertex and index buffer from a staging buffer.
- Shader packs with compute shaders, image atomics and geometry shaders (Rethinking Voxels, Minecraft 1.21.10 with Iris) went from 2.2 to 11.1 fps (#68):
- Image atomics no longer copy their textures around every draw. Metal on macOS 27 leaves atomics out of the usage it reports for a texture, so WineMetalGL took two voxel volumes, 12–25 MB each, for textures without atomic storage, thousands of times a second.
- Programs that declare more than 16 samplers and use fewer link. Unused samplers and images take no slot, and shared shader-pack headers no longer fail with "too many samplers in one stage".
- Geometry shaders run each listed vertex once, on the GPU, inside the draw's render pass: 586 render passes a frame became 40.
WineMetalGL Settings
- Arm64 Fixes: Game Fixes has a Wine Fixes and an Arm64 Fixes section, with a switch per game (#68, #70):
- Minecraft installs the core and the glue and adds the JVM arguments that load them to every Prism Launcher instance, official launcher installation and Modrinth App instance. Turning it off puts each launcher's own arguments back.
- OpenMW installs the glue and the core into OpenMW.app.
- Installing has three buttons, always shown (#69):
- Install finds every Wine on your Mac (Wine apps, Homebrew, MacPorts, Whisky, MetalSharp, and any other Spotlight finds) and installs into its default prefix.
- CrossOver finds bottles and copies of CrossOver anywhere, and installs into a bottle even without CrossOver.app.
- Custom Install installs into any Wine and prefix chosen in Finder.
- The app shows as WineMetalGL, with a new GL icon (#69).
Changed
- Shader math: shaders compile with relaxed math that keeps arithmetic in the order the shader writes it (#68). SpaceEngine stays correct, without the cost of 3.5.0's safe math.
WINEMETALGL_SAFE_MATH=1selects safe math, and=0now selects relaxed math that may reorder arithmetic. install-crossover.shinstalls into a bottle without CrossOver: it writes theopengl32override into the bottle'suser.reg(#69).
Notes
- The first launch after updating recompiles shaders and pipelines, so expect normal compile stutter once.
WINEMETALGL_PASS_PROFILE=1logs the GPU time each kind of Metal encoder takes, by its target and programs, for performance reports.
WineMetalGL 3.5.0
Game compatibility update
WineMetalGL 3.5.0 fixes rendering in several games, turns on x87 acceleration for 32-bit id Tech 4 games, and ships WineMetalGL Settings as a disk image that updates itself and applies game fixes.
Games
- Doom 3: BFG Edition starts and runs, at 60 fps with x87 acceleration (#25, #61). Its GLSL 1.50 shaders redeclare built-ins (
out vec4 gl_Position;) and use compatibility ones without asking for the compatibility profile, as GL drivers allow. They now compile. - SpaceEngine (#35):
- OpenMW (Morrowind), natively on the arm64 core (#42):
- Post-processing (
bloomlinear) renders instead of a black window (#64). Generic attribute 0 now readsglVertexPointer's array, as other drivers do. - Shadows reach past the shadow map's far plane. Depth comparisons against 24-bit depth clamp their reference, as GL requires.
- The statistics overlay's text (F3, osgText) shows (#65).
glCallListis 3× faster (15.8 → 5.3 µs a call), which gives a stable 60 fps.
- Post-processing (
- Quake 4 starts and runs at 60 fps (#58, #59). WineMetalGL Settings applies its display-mode and
r_useSMPfixes.
x87 acceleration
Rosetta runs x87 floating-point code, which 32-bit games use for their math, as slow soft-float. With x87 acceleration, WineMetalGL starts x87sidecar when a 32-bit game loads OpenGL, in any Wine, CrossOver included (#59). Quake 4's heaviest scenes went from 24 to 62 fps.
It is on by default for Quake 4, Doom 3 and Doom 3: BFG Edition (#61). Turn it on for every 32-bit game with WINEMETALGL_X87=1 (the Settings app's x87 Acceleration switch), or off for these too with =0.
WineMetalGL Settings
The app now comes as a disk image (WineMetalGL-Settings-3.5.0.dmg) that carries a whole runtime (#60):
- Updates itself. On launch it offers a newer release. It checks the download's signature and checksum, replaces itself, and updates WineMetalGL in every bottle and prefix it is installed in.
- Game fixes, on by default. It finds Quake 4, SpaceEngine and Wolfenstein: The New Order in your bottles and prefixes, and applies their fixes. It backs up each file it replaces to
~/Library/Application Support/WineMetalGL/Backups.
Changed
- Shaders compile with Metal's safe math (#62). Arithmetic runs in the order the shader writes it, as GL drivers compile GLSL. Relaxed math reordered products that SpaceEngine keeps finite, and its gas giants came out NaN. Frame benchmarks do not change. Arithmetic-heavy shaders can be slower, and
WINEMETALGL_SAFE_MATH=0restores relaxed math.
Notes
- The first launch after updating recompiles shaders and pipelines, so expect normal compile stutter once.
Supported Games (Confirmed Playable);
Doom (2016)
Foundation
Space Engine
Soma
Dead Cells
Foundation
Portal (1)
Casette Beasts
Quake 4
Wolfenstein; New Total Order
The Elder Scrolls III; Morrowind with OpenMW
Doom 3 / Doom 3 (BFG)
7 Days To Die (-force-glcore)
Rage
WineMetalGL 3.4.0: Performance update (DOOM 2016 at a stable 60 fps on M4, no upscaling)
Performance update
WineMetalGL 3.4.0 is a performance release. Games spend less CPU time per frame, stutter less while loading, and keep the GPU busy with drawing instead of waiting.
DOOM (2016) now runs at a stable 60 fps at native resolution, with no upscaling and no thermal throttling, on a MacBook Air with M4.
What to expect
Measured with the new performance probe (tests/wine/perf_probe.py) against 3.3.1. The figures are CPU time per frame, under Wine 11 on Apple M4.
- Streaming buffers and textures.
- Per-draw uniform buffer updates are about 9× faster: 21.3 → 2.3 ms per 1000 draws.
- Invalidating buffer maps are about 10× faster: 207 → 19 ms per frame, with Metal memory down from 826 to 68 MiB.
- Uploads from pixel buffers no longer wait for the GPU: 1.1 → 0.4 ms.
- Texture uploads in older formats.
- BGR, 565, 4444, 5551, luminance, float and
8_8_8_8uploads are about 25× faster: 67 → 2.7 ms for nine 512² uploads. The results are bit-identical. - Auto-mipmapped textures are about 3× faster: 37 → 13 ms.
- BGR, 565, 4444, 5551, luminance, float and
- Older OpenGL games.
- Display lists are 44% faster.
- Client-side vertex arrays are 27% faster, with no more CPU conversion.
- Index buffer updates no longer stall on the GPU: 4.1 → 0.7 ms.
- Fewer render-pass breaks and GPU stalls.
- Fence polling commits 70% fewer command buffers.
glFlushmid-frame no longer splits the frame: commits 31 → 2.- GPU timer queries commit 92% fewer command buffers.
glReadPixels(GL_BGRA)into a pixel buffer no longer waits: 4.6 → 0.6 ms.- A
glClearfollowed by an upload no longer costs an extra pass. - Multisampled windows resolve without an extra pass.
glInvalidateFramebuffernow skips storing and reloading discarded attachments.
- Separate shader objects. Switching program-pipeline stages no longer recompiles pipelines: 23.6 → 1.5 ms per frame.
- Faster loading.
- New on-disk shader cache: a program linked again in a later launch skips compiling and translating its shaders. Linking 60 programs takes 107 → 30 ms.
- The pipeline cache is read in the background, so a large cache no longer holds up the first frames.
New settings
WINEMETALGL_SHADER_CACHE=0turns off the on-disk shader cache in~/Library/Caches/WineMetalGL/shaders.WINEMETALGL_GPU_TIMERS=0timesGL_TIME_ELAPSEDqueries by committing command buffers, as before.
Notes
- The pipeline cache now stops growing at 256 MB, down from 1 GB, so it always loads quickly.
- The first launch after updating builds the new shader cache, so expect normal compile stutter once.
Full details: #57.
WineMetalGL 3.3.1
What's Changed
- Hotfix 3.3.1: CrossOver 27 Preview installs that load correctly
WineMetalGL 3.3.0
Fixes and Improvements:
- Fixed faulty shaders with SpaceEngine
- Fixed Fault Call with Doom 3 BFG
- Fixed Wolfenstein Total New Order failing to load / Audio crash bug, provided fixed F-Audio dll
- Fix OpenMW loading and provide native Arm64 Glue Shim
- Fix SOMA texture / lighting issues
- Fix Doom Performance issues
- Added UpscaleGL Feature (Performance, Balanced, Quality)
- Fixed invariant vertex shader position persistence
- Fixed Display Driver issue
- Fixed Casette Beats not loading / presenting incorrect textures because WineMetalGL reported its driver name as 'Apple'
- Added a complete logging system for WineMetalGL
- Improved performance and rendering issues with Foundation
- Added GLES 2.0 -> 3.2 conformance and support
- Portal (1) now works without texture invariance issues
WineMetalGL Settings App (Download WineMetalGL-Settings-3.3.0.zip And Open It):
- You can now download a tiny developer-signed WineMetalGL helper app built in Swift UI with liquid glass. From here, you are able to toggle performance/balanced/quality upscaling, as well as toggle logs on / off and open the folder they are contained in. You can also install it if not installed both into crossover or your dedicated wine prefix, and toggle WineMetalGL on / off. Only works with MacOS 26 or later.
Game Specific Patch Files:
- Game-Specific Patch Files now contains per-game dlls for games that need them rather than forcing you to figure it out on your own. In this release, there are files for: Space Engine, WolfenStein New Total Order, and The Elder Scrolls III: Morrowind with OpenMW. Point claude or codex at this file if you need help installing it into your wine.
Install (No Settings Application)
Requires x86_64 Wine 11.x (under Rosetta) on macOS 15 or later.
tar -xzf winemetalgl-3.2.0-x86_64.tar.gz
cd winemetalgl-3.2.0-x86_64
curl -LO https://github.com/metalsharp/WineMetalGL/releases/download/winemetalgl-3.2.0/install-wine-module.sh
curl -LO https://github.com/metalsharp/WineMetalGL/releases/download/winemetalgl-3.2.0/install-crossover.shStock Wine (WineHQ or your own build)
sh install-wine-module.sh "/Applications/Wine Stable.app" ~/my-prefix- The first argument is the Wine app or the directory that holds
bin/wine. - The prefix is created if it doesn't exist.
- Run it once per prefix.
- To go back to Wine's own OpenGL for one run:
WINEDLLOVERRIDES=opengl32=b wine program.exe.
CrossOver
sh install-crossover.sh "My Bottle"- Pass the bottle's name or its folder.
- Nothing is copied into CrossOver.app. The module goes into
~/Library/Application Support/WineMetalGL. - Run it once per bottle.
- To go back to CrossOver's OpenGL, remove the
opengl32override in the bottle's Wine Configuration (Libraries). - Tested on CrossOver 26.3. CrossOver 27's arm64 Wine isn't supported yet (#13).
Contributors:
@abotkin - wine: show child windows over GL windows; present front-buffer drawing
@bmichotte - Several Foundation Performance Issue Commits
WineMetalGL 3.2.0
WineMetalGL 3.2.0 fixes the memory growth in SOMA (#16) and texture feedback reads that broke in 3.1.0. It also adds LATC and 3Dc compressed textures and runs on macOS 15.
Updated installers (2026-10-14, #27): stock Wine and CrossOver now have separate install scripts. The CrossOver one no longer writes into CrossOver.app, which fixes #22 and #23. The package itself is unchanged, but the install-wine-module.sh inside it is the old one, so download the scripts below.
Install
Requires x86_64 Wine 11.x (under Rosetta) on macOS 15 or later.
tar -xzf winemetalgl-3.2.0-x86_64.tar.gz
cd winemetalgl-3.2.0-x86_64
curl -LO https://github.com/metalsharp/WineMetalGL/releases/download/winemetalgl-3.2.0/install-wine-module.sh
curl -LO https://github.com/metalsharp/WineMetalGL/releases/download/winemetalgl-3.2.0/install-crossover.shStock Wine (WineHQ or your own build)
sh install-wine-module.sh "/Applications/Wine Stable.app" ~/my-prefix- The first argument is the Wine app or the directory that holds
bin/wine. - The prefix is created if it doesn't exist.
- Run it once per prefix.
- To go back to Wine's own OpenGL for one run:
WINEDLLOVERRIDES=opengl32=b wine program.exe.
CrossOver
sh install-crossover.sh "My Bottle"- Pass the bottle's name or its folder.
- Nothing is copied into CrossOver.app. The module goes into
~/Library/Application Support/WineMetalGL. - Run it once per bottle.
- To go back to CrossOver's OpenGL, remove the
opengl32override in the bottle's Wine Configuration (Libraries). - Tested on CrossOver 26.3. CrossOver 27's arm64 Wine isn't supported yet (#13).
Changes
- Memory growth (#16): Metal objects created during GL calls are now released when the call returns.
- Texture feedback: reads of a texture that is also being rendered to are correct again; this broke in 3.1.0.
- Steam overlay: its GL calls no longer raise errors or disturb the game's matrices.
- Textures: LATC and 3Dc compressed formats are supported (SOMA's normal maps use 3Dc).
- macOS 15: the GPU tests all pass. There are fallbacks for samplers that ignore their LOD bias and for virtual machine GPUs.
- Logging:
WINEMETALGL_LOG=1logs each GL error with the call and its arguments, andWINEMETALGL_STATS=1reports Metal memory use.
Downloads
winemetalgl-3.2.0-x86_64.tar.gz: the Wine module and core.winemetalgl-3.2.0-arm64-core.tar.gz: the arm64 core only. It has not been run inside an arm64 Wine yet.install-wine-module.sh,install-crossover.sh: the installers.SHA256SUMS.txt: checksums for all of the above.
The libraries are Developer ID signed and notarized. WineMetalGL 3.3.0 will release once I have stabilized all current issues as much as possible.
WineMetalGL 3.1.0
WineMetalGL 3.1.0 is a performance release of the OpenGL 4.6 Wine module. GL calls, draws, uploads, readbacks and shader builds cost less across OpenGL 3.0 to 4.6, render targets keep Apple GPUs' lossless compression, and window back buffers can be upscaled with MetalFX following a Wine's DXMT setting. It also fixes the causes of the indirect-draw stalls and the skinned-mesh pipeline failure reported in #12.
DOOM (2016) on its OpenGL renderer, under MetalSharp's Wine 11.17 on an Apple M4, went from 20 to 25 fps on 3.0.0 to a stable 60 fps, as played.
Measured
| What | 3.0.0 | 3.1.0 |
|---|---|---|
| GL call that returns nothing, stock Wine 11.0 (64 / 32-bit) | 854 / 906 ns | 75 / 81 ns |
| Same, MetalSharp Wine 11.17 (64 / 32-bit) | 117 / 155 ns | 78 / 78 ns |
| Draw with a flat varying (Rosetta) | 21.1 µs | 4.9 µs |
| First draws of 24 freshly linked programs | 809 ms (worst 108 ms) | 367 ms (worst 48 ms) |
| 2048² RGB8 / BGRA-rev / RGBA16F upload (Rosetta) | 206 / 244 / 243 ms | 4.4 / 1.0 / 1.9 ms |
| 2048² RGBA / BGRA readback conversion (Rosetta) | 207 / 192 ms | 1.0 / 0.9 ms |
Render-target GPU time, PixelFormatView vs compressed (M4) |
4.27 ms | 1.18 ms |
| DOOM (2016), MetalSharp, Apple M4, as played | 20–25 fps | 60 fps |
Changes
-
Wine module call batching: GL calls that return nothing and take values are batched into one unix call.
WINEMETALGL_BATCH=0turns it off. -
Per-draw CPU cost:
- sampler, vertex-input, target, depth/stencil and uniform state is reused between draws;
- rewritten index lists are kept per element-buffer range, and fans, quads and loops of array draws share index patterns.
-
Pixel transfers:
- fast paths for common upload and readback formats;
- CPU reads wait only for the GPU writes they need;
GL_RED/GL_FLOATreads into a pack buffer no longer wait for the GPU, which removed an 11 ms stall per DOOM frame.
-
Shaders:
- Metal functions compile in the background after link (
WINEMETALGL_PREWARM=0turns it off), and compile and link no longer hold the share-group lock; - shaders compile in Metal's relaxed math mode, which keeps infinities and NaN (
WINEMETALGL_SAFE_MATH=1for safe math); invariantoutputs preserve invariance.
- Metal functions compile in the background after link (
-
GPU memory: textures and render targets keep Apple GPUs' lossless compression.
PixelFormatViewis kept only where a view reinterprets the format. -
Render passes: memory barriers and occlusion queries end fewer render passes.
-
Indirect draws (#12):
glDraw*IndirectandglMultiDraw*Indirecthand GPU-written commands to Metal's indirect draws instead of waiting and reading them on the CPU;glDispatchComputeIndirectno longer waits for the GPU;- draws that need the command on the CPU (vertex conversion, index rewriting, emulated stages, counting queries,
gl_BaseVertex/gl_BaseInstance) keep the previous path.
-
Integer attributes (#12): attributes whose signedness differs from the shader input, such as unsigned bone indices read as
ivec4, no longer fail pipeline creation. They read as GL reads them. -
MetalFX: window back buffers can be presented through the MetalFX spatial scaler into a larger drawable, on GPUs MetalFX supports. The setting follows DXMT's:
WINEMETALGL_METALFX=0or=<factor>;- otherwise
DXMT_METALFX_SPATIAL_SWAPCHAIN=0turns it off; - otherwise
d3d11.metalSpatialUpscaleFactorfromDXMT_CONFIG,DXMT_CONFIG_FILEor the Wine installation'setc/dxmt.conf.
The back buffer keeps the window's size, so GL behaviour does not change.
-
Statistics:
WINEMETALGL_STATS=1also reports:- GPU time per frame and where draws spend CPU time;
- why render passes end, and command buffers committed;
- readback paths;
- indirect commands read by the GPU and by the CPU.
-
Fixes:
- asynchronous
glReadPixelsignoredGL_PACK_SWAP_BYTES; - fixed-function raster uniforms did not mark the uniforms changed;
- image units bound to undefined texture levels read through invalid views.
- asynchronous
Evidence
3.1.0 did not rerun the full CTS lists. Its OpenGL 4.6 conformance claim is 3.0.0's: the KHR-GL46 mustpass runs at 49c5099 (15,156 passes, 3 failures, 1 compatibility warning), and those are the baselines the package's evidence/ directory carries. Each change in 3.1.0 was checked by tests of the code it touches, each one failing with its change reverted:
- GPU tests: 230 of 230.
- Host tests: 54 of 54.
- Wine fixtures: 146 of 146, which is 73 fixtures, each run as an x86_64 and an i386 guest on stock Wine 11.0. This includes the new
opengl_present(swap intervals 0 and 1 across resizes, with and without MetalFX). - CTS: the
KHR-GL46groups of each changed path, natively. Indirect draws, shader draw parameters, indirect parameters, compute, vertex attribute binding and gpu_shader5 give 161 of 161. - DOOM (2016) under MetalSharp.
Packages
winemetalgl-3.1.0-x86_64.tar.gz: the Wine module and the x86_64 core, for x86_64 Wine 11.x under Rosetta.install-wine-module.sh WINE [PREFIX]installs it (docs/release.md).winemetalgl-3.1.0-arm64-core.tar.gz: the arm64 core and the driver ABI header. It has not yet run inside an arm64 Wine.
The Mach-O libraries are signed with a Developer ID (hardened runtime, secure timestamp) and notarized. Each package carries a SHA256SUMS manifest; SHA256SUMS.txt covers the archives.
Known limits
glMultiDraw*IndirectCountstill reads its draw count on the CPU after the GPU writes it.- CrossOver 27's aarch64 Wine needs an ARM64/ARM64EC build of the module, which this release does not include (#12).
- Under MetalSharp, OpenGL games follow
dxmt.conf's MetalFX factor, but not MetalSharp's MetalFX on/off switch, which only reaches its Direct3D pipelines.
Full changes: winemetalgl-3.0.0...winemetalgl-3.1.0
WineMetalGL 3.0.0
WineMetalGL 3.0.0 reports OpenGL 4.6, core and compatibility profile, under Wine on Metal. It is the first release shipped as a Wine module of its own: it installs into an unmodified Wine 11.x, with no Wine patches. Contexts that asked for 4.5 or less get 4.6, since core profiles are backward compatible as on Windows drivers. Legacy wglCreateContext contexts get the 4.6 compatibility profile.
The claim rests on the Khronos CTS KHR-GL46 mustpass list, recorded at 49c5099:
- configuration 1 natively;
- configurations 1 and 3 under stock Wine 11.0 with the module.
Each run gives 15,156 passes, 3 failures and 1 compatibility warning, with no timeouts; the 4,554 NotSupported cases are optional extensions and limits. OpenGL 4.4 and 4.5 have no mustpass list of their own: KHR-GL46 runs their tests.
DOOM (2016) on its OpenGL renderer under MetalSharp's Wine 11.17 with the module, in an OpenGL 4.6 compatibility context on an Apple M4:
What OpenGL 4.4, 4.5 and 4.6 bring
- OpenGL 4.4:
- buffer storage, including persistent and coherent mappings;
- multi-bind, clear texture, query buffer objects, enhanced layouts;
- mirror clamp to edge, stencil-only textures;
- arbitrary border colours.
- OpenGL 4.5:
- direct state access for every object type;
- clip control, cull distances, inverted conditional rendering;
- robustness, ES 3.1 compatibility;
- texture sub-image reads, derivative control, texture and image sample queries.
- OpenGL 4.6:
- SPIR-V shaders;
- pipeline statistics queries, transform feedback overflow queries;
- indirect draw counts and shader draw parameters;
- shader group vote, atomic counter operations;
- anisotropic filtering, polygon offset clamp;
- no-error contexts, parallel shader compile.
- Extensions:
GL_ARB_shader_viewport_layer_array,GL_EXT_texture_shadow_lod,GL_EXT_texture_sRGB_decode;GL_AMD_pinned_memory.
- wined3d: reports Direct3D feature level 11_1 through the module, where Apple's OpenGL gives 9_3.
The Wine module
- Its own
opengl32.dll(a forwarder), pluswinemetalgl.dllandwinemetalgl.so. - WoW64 thunks, so 32-bit programs run in a 64-bit Wine.
- It builds against the headers of any Wine 11.x. It was tested on stock Wine 11.0 (
--with-opengl --with-vulkan) and on MetalSharp's Wine 11.17. patches/wineis retired.install-wine-module.sh WINE [PREFIX]copies the module and the core into a Wine installation, andopengl32.dllinto a prefix (docs/release.md).
Performance
- Per-draw CPU cost was cut for heavy OpenGL games (DOOM (2016)):
- vertex attribute conversions are kept per buffer;
- pack-buffer reads are asynchronous;
- index-range scans are cached;
- redundant encoder state is skipped;
- framebuffers are shared between contexts.
- Compiles, links and Metal functions of identical shaders are reused. Programs rebuilt from the same shaders no longer recompile.
Packages
winemetalgl-3.0.0-x86_64.tar.gz: the Wine module and the x86_64 core, for x86_64 Wine 11.x under Rosetta.module/x86_64-unix:winemetalgl.soandlibwinemetalgl.dylib, forlib/wine/x86_64-unix.module/x86_64-windowsandmodule/i386-windows:winemetalgl.dllandopengl32.dll.- The package also carries the evidence behind this release.
winemetalgl-3.0.0-arm64-core.tar.gz: the arm64 core and the driver ABI header, for a native arm64 Wine.- Its evidence is the native CTS runs.
- It has not yet run inside an arm64 Wine.
The Mach-O libraries are signed with a Developer ID (hardened runtime, secure timestamp) and notarized. Each package carries a SHA256SUMS manifest; SHA256SUMS.txt covers the archives.
3.0.0 is a GitHub release only; MetalSharp's runtime bundle is updated separately.
Other evidence
- CTS rechecks: every non-Pass case of the
KHR-GL30toKHR-GL43baselines was rerun in configurations 1 to 4, natively and on stock Wine 11.0. The remaining failures are listed with reasons intests/cts/known-failures.json. - Wine fixtures: 142 of 142, which is 71 fixtures, each run as an x86_64 and an i386 guest on stock Wine 11.0.
- Game corpus: 14 of 14 match their reference frames, including
scene4xat OpenGL 4.4, 4.5 and 4.6. - Frame times (
docs/performance.md):- 11 of 14 entries are as fast as or faster than 2.4.0.
scene33-trace,scene4x-core42andscene4x-core43read slower than 2.4.0's figures from the night before. The previous night's 3.0 development core, measured in the same session, gives the same times, so the machine was slower for those GPU-bound scenes, not the core.
- Unit tests: host 49 of 49, GPU 217 of 217.
- CI:
- The new Metal workflow runs the GPU tests on GitHub's Apple-silicon runners, which use macOS 15.
- Three cases are reported there without being required: sampler LOD bias needs macOS 26, and the virtual GPU ignores a negative base vertex (
docs/unsupported.md#macos-15).
- DOOM (2016) runs under MetalSharp with the module.
Environment
WINEMETALGL_LOG=1..3raises the log level.WINEMETALGL_TRACE=1logs every GL call.WINEMETALGL_STATS=1logs per-frame statistics, with per-command profiles and vertex conversion counts.WINEMETALGL_VENDOR/WINEMETALGL_RENDERERreplace theGL_VENDOR/GL_RENDERERstrings.WINEMETALGL_MAX_FEATURE_LEVEL=4.5(for example) caps the context version.WINEMETALGL_DEV_MAX_VERSIONis a development setting for CTS coverage runs, not a user setting.
Full changes: winemetalgl-2.4.0...winemetalgl-3.0.0
WineMetalGL 2.4.0
WineMetalGL 2.4.0 reports OpenGL 4.3, core and compatibility profile, under Wine on Metal. Contexts that asked for 4.2 or less before now get 4.3: core profiles are backward compatible, as on Windows drivers. Legacy wglCreateContext contexts get the 4.3 compatibility profile. Nothing on macOS offered these features before: Apple's OpenGL stops at 4.1.
The claim rests on the Khronos CTS KHR-GL43 mustpass list, configurations 1 to 4, each under Wine and natively, recorded at f4ecccd.
What OpenGL 4.3 brings
- Compute shaders.
- Work groups and shared memory.
glDispatchComputeandglDispatchComputeIndirect.- Conditional dispatch.
- Shader storage buffers in every stage. That includes the emulated geometry and tessellation stages, through a per-stage Metal argument buffer.
- Atomics,
std430layouts and unsized arrays. glShaderStorageBlockBinding.
- Atomics,
- Program interface queries (
glGetProgramResource*) and explicit uniform locations. - Vertex attribute bindings (
glBindVertexBuffer,glVertexAttrib*Format). - Texture views of any level and layer range, including views of views.
- Texture buffer ranges and texture query levels.
- ETC2/EAC compressed formats (native on Apple GPUs).
- Uploads of uncompressed data to S3TC, BPTC, ETC2 and EAC formats are compressed on the CPU.
glGetTexImageof compressed formats is decoded on the GPU.
- Multi-draw indirect,
glClearBufferData/glClearBufferSubData, framebuffers without attachments, internalformat query 2 (glGetInternalformati64vand every GL 4.3 query), GLSL ES 3.00 shaders (GL_ARB_ES3_compatibility), arrays of arrays (also in subroutine uniforms),gl_Layer/gl_ViewportIndexin fragment shaders, stencil texturing, andGL_ARB_texture_barrier.
Fixes found on the way
- RGB32 buffer textures (
GL_RGB32F/I/UI, GL 4.0). They were advertised since 2.3.0, butglTexBufferrefused them. Metal has no RGB32 formats, so the texels are now expanded on the GPU into an RGBA32 copy. - Layered rendering into 1D array textures wrote every layer to layer 0.
- Atomic counters:
- A shader over the per-stage limit now fails to link.
- A counter takes the default offset set by
layout(binding, offset) uniform atomic_uint;.
- Error codes:
glFramebufferTextureandglTexBufferRangenow raise the errors the spec requires. - Shader compilation:
layout(binding)now works withGL_ARB_shader_storage_buffer_objectbelow GLSL 4.20, and several SPIR-V to MSL corner cases now compile. Details are inDEPENDENCIES.md.
Conformance totals
| OpenGL | Conformance % | Features | Unsupported % |
|---|---|---|---|
| 3.0 | 99.88% | GLSL 1.30, framebuffer objects, vertex array objects, transform feedback, integer textures | 2.28% |
| 3.1 | 100% | Instancing, texture buffers, uniform buffers, primitive restart | 2.38% |
| 3.2 | 100% | Profiles, geometry shaders, sync objects, multisample textures, base vertex | 0.69% |
| 3.3 | 99.98% | GLSL 3.30, sampler objects, timer queries, instanced arrays, dual-source blending | 3.59% |
| 4.0 | 99.98% | Tessellation, GLSL 4.00, double precision, indirect draws, per-sample shading | 12.18% |
| 4.1 | 99.98% | Separate shader objects, program binaries, viewport arrays, 64-bit attributes | 12.15% |
| 4.2 | 99.96% | Image load/store, atomic counters, immutable texture storage | 11.73% |
| 4.3 | 99.96% | Compute shaders, shader storage buffers, debug output, texture views | 17.65% |
| 4.4 | - | Buffer storage, multi-bind, texture clears, enhanced layouts | 100% |
| 4.5 | - | Direct state access, clip control, robustness, cull distances | 100% |
| 4.6 | - | SPIR-V shaders, anisotropic filtering, indirect draw counts | 100% |
Each row is the worst of its 8 runs: configurations 1 to 4 of mustpass.xml, under Wine and natively.
- The 4.3 row was recorded at
f4ecccd. - The 3.3 to 4.2 rows keep their 2.3.0 baselines (
851476e). Their non-Pass cases were run again at0a20fbein the same 8 configurations (tests/cts/recheck/), and those results replace the baselines'.- Two former failures pass in 4.3 contexts:
name_gettersandnon_precision_qualifiers. - Every case of KHR-GL33 to KHR-GL42 is also part of KHR-GL43.
- Two former failures pass in 4.3 contexts:
- The 3.0 to 3.2 rows keep their 2.1.0 evidence (
14eaa75).
KHR-GL43 passes the same 13,041 cases in every run. The non-passing cases are CTS defects, each with its reason in tests/cts/known-failures.json:
rgb9_e5renderbuffers.map_buffer_alignment(it binds the GL 4.4GL_QUERY_BUFFER).transform_feedback2_states(it calls a GL 4.5 entry point).texture_view.view_sampling. It leaves cube-map views on linear filtering and expects each face filtered on its own; Metal always filters cube maps across faces.
This is not a Khronos-adopted conformance submission. What Unsupported % counts, and why each failing case fails: Unsupported.
Not implemented
- OpenGL 4.4 and later. That covers multi-bind, texture clears, enhanced layouts, query buffer objects, direct state access and SPIR-V shaders. The next milestone (3.0.0) is GL 4.6.
- Multisample images.
GL_MAX_IMAGE_SAMPLESis 0, the GL minimum, because Metal shaders cannot write multisample textures. - Sampler border colors. Only Metal's three are available: transparent black, opaque black and opaque white.
- Non-seamless cube map filtering. Metal always filters across cube faces.
- The full list is in
docs/unsupported.md.
Packages
The two packages are not interchangeable: winemac.so loads the core of its own architecture, and Wine falls back to Apple's OpenGL when it cannot.
winemetalgl-2.4.0-x86_64.tar.gz: a drop-in for MetalSharp's x86_64 Wine 11.17 under Rosetta.artifacts/wine-driver/*goes tolib/wine/x86_64-unix: the core, plus patchedwinemac.so,win32u.soandopengl32.so.artifacts/guest/i386andartifacts/guest/x86_64holdopengl32.dllforlib/wine/i386-windowsandlib/wine/x86_64-windows.- The bundled Wine modules are built from MetalSharp's Wine and match its ABI.
- With any other Wine 11.17, build it with
patches/wine(unchanged since 2.3.0,docs/building.md) and take onlylibwinemetalgl.dylib.
winemetalgl-2.4.0-arm64-core.tar.gz: the arm64 core, the driver ABI header andpatches/wine, for a native arm64 Wine built with the patches.- Its evidence is the native CTS runs.
- It has not yet run inside an arm64 Wine.
Each package carries a SHA256SUMS manifest; SHA256SUMS.txt covers the archives.
2.4.0 is a GitHub release only. MetalSharp's runtime bundle stays on 2.2.0 until WineMetalGL reaches OpenGL 4.6.
Other evidence
- Wine fixtures: 118 of 118, which is 59 fixtures, each run as an x86_64 and an i386 guest in one WoW64 prefix.
- New:
opengl_gl43, which uses a 4.3 context through Wine'sopengl32. - Moved into the gate: the compute, image, indirect and tessellation fixtures.
- New:
- Game corpus: 11 of 11. The new
scene4x-core43renders the 4.1 reference frame through GL 4.3: a multi-draw indirect terrain and a compute-shader tonemap that counts its pixels in a shader storage block. It differs from the reference in 0.0056% of pixels, ascore41andcore42do. - Frame times (
docs/performance.md): every entry is within budget, at 0.82x to 1.02x of the 2.3.0 core measured the same day.scene4x-core43takes 1.98 ms a frame. - Unit tests: host 45 of 45, GPU 164 of 164.
Environment
WINEMETALGL_LOG=1..3raises the log level.WINEMETALGL_TRACE=1logs every GL call.WINEMETALGL_STATS=1logs per-frame statistics.WINEMETALGL_VENDOR/WINEMETALGL_RENDERERreplace theGL_VENDOR/GL_RENDERERstrings, for games that refuse unknown vendors.WINEMETALGL_MAX_FEATURE_LEVEL=4.2(for example) caps the context version, for programs that misbehave on 4.3.LaterEntryPoints(registry,docs/building.md) gives OpenGL loaders the entry points of versions above 4.3. Dead Cells no longer needs it: the 4.2 and 4.3 entry points its loader requires are part of 4.3 contexts.WINEMETALGL_DEV_MAX_VERSIONis a development setting for CTS coverage runs, not a user setting. It raises contexts above what the core implements, andGL_RENDERERthen says so.
Full changes: winemetalgl-2.3.0...winemetalgl-2.4.0

