Skip to content

DXMT Build

The dxmt-er-build repository builds a DXMT v0.80 runtime with an Eternal Return specific pixel output sanitization patch. The patch is intended to reduce the flashing and broken graphics observed in Eternal Return.

It adds the d3d11.sanitizeOutput option and enables it by default only for EternalReturn.exe. It does not enable other experimental options such as dxgi.forceSDR, sampleNaNToZero, or defuseFma.

The build requires macOS, Xcode Command Line Tools, git, curl, cmake, meson, and ninja. A Wine build tree is also required to build the builtin Wine DLLs and .so files.

The default Wine build tree path is:

./wine-build/build64

Use WINE_BUILD when the tree is elsewhere.

Terminal window
WINE_BUILD=/path/to/wine-build/build64 ./scripts/build-dxmt.sh

Fetch the DXMT toolchains and source first.

Terminal window
./scripts/fetch-toolchains.sh
./scripts/fetch-dxmt.sh

Then build the DXMT runtime with the Wine build tree.

Terminal window
WINE_BUILD=/path/to/wine-build/build64 ./scripts/build-dxmt.sh

If the Wine build tree is linked at the default path, run:

Terminal window
./scripts/build-dxmt.sh

The build produces a dxmt-runtime directory and a tarball artifact.

dxmt-runtime/
i386-windows/
x86_64-windows/
x86_64-unix/
artifacts/
dxmt-v0.80-builtin.tar.gz
dxmt-v0.80-builtin.tar.gz.sha256

The archive extracts into dxmt-v0.80-builtin/. The runtime and archive include the relevant DXMT and third-party license files.

Use the install script when installing into a Wine Stable layout. Existing files are preserved in timestamped backups.

Terminal window
./scripts/install-to-wine-stable.sh

Configure Wine to prefer the builtin DXMT DLLs.

d3d10core = builtin,native
d3d11 = builtin,native
dxgi = builtin,native
winemetal = builtin,native

When integrating with the launcher, keep the Wine root and prefix-local DLLs on the same DXMT version. Stale prefix-local DLLs can cause an older DXMT build to load even after a new runtime is installed.

The diagnostics concluded that the visible issue is more likely an FP compatibility problem at the D3D shader to macOS graphics backend boundary than a generic Wine data transport issue such as pointer truncation, row pitch, stride, or buffer size handling.

The current workaround replaces non-finite pixel shader outputs, such as NaN or Inf, with 0.0. Conceptually, the flow is:

game DXBC pixel shader
-> DXMT LLVM/AIR conversion
-> injected non-finite output epilogue
-> Metal shader compilation
-> GPU execution
-> render-target write

The operation is close to a branchless select, so its cost is predictable but not free. It is not made global because D3D conformance can require NaN and Inf to remain in float render targets.

For an Eternal Return A/B test, disable the shader cache and compare with the sanitizer on and off.

Terminal window
DXMT_SHADER_CACHE=0 /path/to/your/steam-launcher.sh
DXMT_SHADER_CACHE=0 DXMT_DISABLE_OUTPUT_SANITIZE=1 /path/to/your/steam-launcher.sh

The first command checks the sanitized path. The second command disables the workaround for comparison.

A separate diagnostic build exists for CrossOver 26.1.0. It is used to collect shader DXBC dumps, DXMT logs, Xcode .gputrace captures, and non-finite output markers.

Terminal window
./scripts/build-crossover-26.1.0-diagnostic.sh
./scripts/test-crossover-26.1.0-diagnostic.sh

The diagnostic marker turns problem pixels white to locate the issue. It is not the user-facing fix, and release builds should not include diagnostic markers or tracing code.