Skip to content

Releases: metalsharp/WineMetalGL

WineMetalGL 3.7.0

Choose a tag to compare

@github-actions github-actions released this 23 Oct 04:08
8388f52

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.gz is a new package next to the x86_64 one, from scripts/stage-release-arm64.sh:
    • winemetalgl.dll and the opengl32.dll forwarder 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.so and 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.
  • 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.sh works out whether the Wine is an x86_64 Wine or an arm64 one:
    • from the unix side it has (lib/wine/x86_64-unix or aarch64-unix);
    • for a Wine with both, from the prefix's own system32;
    • WINEMETALGL_ARCH overrides the detection.
  • install-crossover.sh reads the bottle's own system32/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] DllPath default built on aarch64-windows;
    • the ARM64X opengl32.dll and winemetalgl.dll in system32, with the i386 ones in syswow64.
  • 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.app is left alone; it already uses WineMetalGL.

WineMetalGL 3.6.0

Choose a tag to compare

@github-actions github-actions released this 22 Oct 04:19
c8ec4ab

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 named new), 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=1 selects safe math, and =0 now selects relaxed math that may reorder arithmetic.
  • install-crossover.sh installs into a bottle without CrossOver: it writes the opengl32 override into the bottle's user.reg (#69).

Notes

  • The first launch after updating recompiles shaders and pipelines, so expect normal compile stutter once.
  • WINEMETALGL_PASS_PROFILE=1 logs the GPU time each kind of Metal encoder takes, by its target and programs, for performance reports.

WineMetalGL 3.5.0

Choose a tag to compare

@github-actions github-actions released this 21 Oct 14:48
56d9048

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):
    • Jupiter, Saturn and the other ringed planets render (#62).
    • The orbit lines render (#63). Geometry shaders now match their inputs to the vertex shader's outputs by location, as GL does, not only by name.
  • OpenMW (Morrowind), natively on the arm64 core (#42):
    • Post-processing (bloomlinear) renders instead of a black window (#64). Generic attribute 0 now reads glVertexPointer'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).
    • glCallList is 3× faster (15.8 → 5.3 µs a call), which gives a stable 60 fps.
  • Quake 4 starts and runs at 60 fps (#58, #59). WineMetalGL Settings applies its display-mode and r_useSMP fixes.

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=0 restores 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)

Choose a tag to compare

@github-actions github-actions released this 20 Oct 13:29
c7ede02

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_8 uploads 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.
  • 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.
    • glFlush mid-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 glClear followed by an upload no longer costs an extra pass.
    • Multisampled windows resolve without an extra pass.
    • glInvalidateFramebuffer now 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=0 turns off the on-disk shader cache in ~/Library/Caches/WineMetalGL/shaders.
  • WINEMETALGL_GPU_TIMERS=0 times GL_TIME_ELAPSED queries 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

Choose a tag to compare

@github-actions github-actions released this 19 Oct 04:36
6039c11

What's Changed

  • Hotfix 3.3.1: CrossOver 27 Preview installs that load correctly

WineMetalGL 3.3.0

Choose a tag to compare

@github-actions github-actions released this 19 Oct 01:23
cc5c07a

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.sh

Stock 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 opengl32 override 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

Choose a tag to compare

@aaf2tbz aaf2tbz released this 14 Oct 05:17
07f4891

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.sh

Stock 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 opengl32 override 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=1 logs each GL error with the call and its arguments, and WINEMETALGL_STATS=1 reports 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

Choose a tag to compare

@aaf2tbz aaf2tbz released this 13 Oct 11:19
994324d

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.

doom_perf

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=0 turns 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_FLOAT reads 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=0 turns 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=1 for safe math);
    • invariant outputs preserve invariance.
  • GPU memory: textures and render targets keep Apple GPUs' lossless compression. PixelFormatView is kept only where a view reinterprets the format.

  • Render passes: memory barriers and occlusion queries end fewer render passes.

  • Indirect draws (#12):

    • glDraw*Indirect and glMultiDraw*Indirect hand GPU-written commands to Metal's indirect draws instead of waiting and reading them on the CPU;
    • glDispatchComputeIndirect no 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=0 or =<factor>;
    • otherwise DXMT_METALFX_SPATIAL_SWAPCHAIN=0 turns it off;
    • otherwise d3d11.metalSpatialUpscaleFactor from DXMT_CONFIG, DXMT_CONFIG_FILE or the Wine installation's etc/dxmt.conf.

    The back buffer keeps the window's size, so GL behaviour does not change.

  • Statistics: WINEMETALGL_STATS=1 also 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 glReadPixels ignored GL_PACK_SWAP_BYTES;
    • fixed-function raster uniforms did not mark the uniforms changed;
    • image units bound to undefined texture levels read through invalid views.

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-GL46 groups 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*IndirectCount still 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

Choose a tag to compare

@aaf2tbz aaf2tbz released this 12 Oct 15:26
6a7cbb2

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:

DOOM (2016) gameplay on WineMetalGL

DOOM (2016) settings with the OpenGL graphics API

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), plus winemetalgl.dll and winemetalgl.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/wine is retired.
  • install-wine-module.sh WINE [PREFIX] copies the module and the core into a Wine installation, and opengl32.dll into 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.so and libwinemetalgl.dylib, for lib/wine/x86_64-unix.
    • module/x86_64-windows and module/i386-windows: winemetalgl.dll and opengl32.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-GL30 to KHR-GL43 baselines was rerun in configurations 1 to 4, natively and on stock Wine 11.0. The remaining failures are listed with reasons in tests/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 scene4x at 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-core42 and scene4x-core43 read 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..3 raises the log level.
  • WINEMETALGL_TRACE=1 logs every GL call.
  • WINEMETALGL_STATS=1 logs per-frame statistics, with per-command profiles and vertex conversion counts.
  • WINEMETALGL_VENDOR / WINEMETALGL_RENDERER replace the GL_VENDOR / GL_RENDERER strings.
  • WINEMETALGL_MAX_FEATURE_LEVEL=4.5 (for example) caps the context version.
  • WINEMETALGL_DEV_MAX_VERSION is 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

Choose a tag to compare

@aaf2tbz aaf2tbz released this 12 Oct 00:06
027d25b

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.
    • glDispatchCompute and glDispatchComputeIndirect.
    • Conditional dispatch.
  • Shader storage buffers in every stage. That includes the emulated geometry and tessellation stages, through a per-stage Metal argument buffer.
    • Atomics, std430 layouts and unsized arrays.
    • glShaderStorageBlockBinding.
  • 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.
    • glGetTexImage of compressed formats is decoded on the GPU.
  • Multi-draw indirect, glClearBufferData/glClearBufferSubData, framebuffers without attachments, internalformat query 2 (glGetInternalformati64v and every GL 4.3 query), GLSL ES 3.00 shaders (GL_ARB_ES3_compatibility), arrays of arrays (also in subroutine uniforms), gl_Layer/gl_ViewportIndex in fragment shaders, stencil texturing, and GL_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, but glTexBuffer refused 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: glFramebufferTexture and glTexBufferRange now raise the errors the spec requires.
  • Shader compilation: layout(binding) now works with GL_ARB_shader_storage_buffer_object below GLSL 4.20, and several SPIR-V to MSL corner cases now compile. Details are in DEPENDENCIES.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 at 0a20fbe in the same 8 configurations (tests/cts/recheck/), and those results replace the baselines'.
    • Two former failures pass in 4.3 contexts: name_getters and non_precision_qualifiers.
    • Every case of KHR-GL33 to KHR-GL42 is also part of KHR-GL43.
  • 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_e5 renderbuffers.
  • map_buffer_alignment (it binds the GL 4.4 GL_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_SAMPLES is 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 to lib/wine/x86_64-unix: the core, plus patched winemac.so, win32u.so and opengl32.so.
    • artifacts/guest/i386 and artifacts/guest/x86_64 hold opengl32.dll for lib/wine/i386-windows and lib/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 only libwinemetalgl.dylib.
  • winemetalgl-2.4.0-arm64-core.tar.gz: the arm64 core, the driver ABI header and patches/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's opengl32.
    • Moved into the gate: the compute, image, indirect and tessellation fixtures.
  • Game corpus: 11 of 11. The new scene4x-core43 renders 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, as core41 and core42 do.
  • 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-core43 takes 1.98 ms a frame.
  • Unit tests: host 45 of 45, GPU 164 of 164.

Environment

  • WINEMETALGL_LOG=1..3 raises the log level.
  • WINEMETALGL_TRACE=1 logs every GL call.
  • WINEMETALGL_STATS=1 logs per-frame statistics.
  • WINEMETALGL_VENDOR / WINEMETALGL_RENDERER replace the GL_VENDOR / GL_RENDERER strings, 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_VERSION is a development setting for CTS coverage runs, not a user setting. It raises contexts above what the core implements, and GL_RENDERER then says so.

Full changes: winemetalgl-2.3.0...winemetalgl-2.4.0