콘텐츠로 이동

DXMT 빌드

dxmt-er-build 저장소는 DXMT v0.80에 이터널리턴 전용 pixel output sanitization 패치를 적용한 런타임을 빌드합니다. 이 패치는 이터널리턴에서 관찰된 섬광과 깨진 그래픽 문제를 줄이기 위한 보정입니다.

패치는 d3d11.sanitizeOutput 옵션을 추가하고 EternalReturn.exe에만 기본 적용합니다. dxgi.forceSDR, sampleNaNToZero, defuseFma 같은 다른 실험 옵션은 켜지 않습니다.

macOS, Xcode Command Line Tools, git, curl, cmake, meson, ninja가 필요합니다. 또한 builtin Wine DLL과 .so를 만들기 위해 Wine build tree가 필요합니다.

기본 Wine build tree 경로는 다음과 같습니다.

./wine-build/build64

다른 경로를 사용한다면 WINE_BUILD로 지정합니다.

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

먼저 DXMT용 toolchain을 준비하고 DXMT source를 가져옵니다.

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

그 다음 Wine build tree를 지정해 DXMT runtime을 빌드합니다.

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

기본 경로에 Wine build tree를 연결해 두었다면 다음처럼 실행할 수 있습니다.

Terminal window
./scripts/build-dxmt.sh

빌드가 끝나면 dxmt-runtime과 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

archive는 dxmt-v0.80-builtin/ 디렉터리로 풀리도록 만들어집니다. runtime과 archive에는 DXMT와 관련 third-party license가 함께 포함됩니다.

Wine Stable 경로에 설치해야 할 때는 설치 스크립트를 사용할 수 있습니다. 기존 파일은 timestamp가 포함된 backup으로 보존됩니다.

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

Wine에서는 DXMT DLL을 builtin 우선으로 사용하도록 override를 맞춥니다.

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

런처에 통합할 때는 Wine root와 prefix-local DLL이 서로 다른 DXMT 버전으로 섞이지 않도록 관리해야 합니다. 오래된 prefix-local DLL이 남아 있으면 새 런타임을 설치해도 이전 DXMT가 로드될 수 있습니다.

진단 결과 이 문제는 Wine의 일반적인 pointer truncation, row pitch, stride, buffer size 문제보다는 D3D shader가 macOS graphics backend로 변환되는 경계에서 발생하는 부동소수점 호환성 문제에 가깝다고 정리되었습니다.

현재 보정은 pixel shader output에 NaN 또는 Inf 같은 non-finite 값이 들어갈 때 이를 0.0으로 바꾸는 방식입니다. 개념적으로는 다음 흐름입니다.

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

이 처리는 branchless select에 가깝고 비용은 예측 가능하지만, 완전히 공짜는 아닙니다. 또한 D3D conformance 관점에서는 NaN/Inf가 float render target에 남아야 하는 경우가 있으므로 전역 기본값으로 두지 않습니다.

이터널리턴을 실행해 보정 적용 여부를 비교할 때는 shader cache를 끄고 A/B 테스트를 진행합니다.

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

첫 번째 명령은 sanitize output이 켜진 상태를 확인합니다. 두 번째 명령은 보정을 끈 비교 실행입니다.

CrossOver 26.1.0 대상으로 별도 diagnostic build도 존재합니다. 이 빌드는 shader DXBC dump, DXMT log, Xcode .gputrace, non-finite output marker를 얻기 위한 용도입니다.

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

진단 marker는 흰색 pixel 출력으로 문제 위치를 확인하기 위한 도구이며, 실제 사용자용 해결책이 아닙니다. 릴리즈 빌드에는 진단 marker와 tracing 코드를 포함하지 않는 것을 기준으로 합니다.