ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

ARM设备运行x86-64 Windows游戏:FEX-Emu、Wine与DXMT技术栈解析

ARM设备运行x86-64 Windows游戏:FEX-Emu、Wine与DXMT技术栈解析 1. 从Madeira这个名字说起一个跨平台兼容层的野心第一次看到Madeira这个项目名我脑子里蹦出来的不是葡萄牙那个产葡萄酒的岛屿而是它背后那串关键词——FEX-Emu、Wine、DXMT、iOS、x86-64。这几个词凑在一起指向的东西其实非常明确在非x86架构的设备上把x86-64的Windows应用和游戏跑起来。而Madeira很可能就是这个技术栈的一个整合封装层或者说是一个面向终端用户的发行版本。为什么我这么判断因为FEX-Emu负责的是指令集翻译它把x86-64的机器码实时翻译成ARM64能执行的指令Wine负责的是Windows API的兼容层让Windows程序以为自己跑在真正的Windows上DXMT则是把Direct3D调用翻译成Metal让图形渲染能在Apple的GPU上跑起来。这三者叠在一起就是一条完整的Windows游戏在ARM设备上运行的链路。Madeira如果是一个整合项目那它的价值就在于把这套复杂的技术栈打包成一个普通人能装、能用的东西。这个方向其实不算新鲜但真正能跑通并且体验可用的方案一直不多。原因很简单指令翻译有性能损耗API兼容有行为差异图形翻译有特性缺失。三层叠加下来任何一个环节出问题用户看到的就是黑屏、闪退或者卡成幻灯片。所以Madeira这类项目要解决的核心问题不是能不能跑而是跑起来之后能不能用。这篇文章我会从技术栈拆解、环境搭建、实际调优、常见故障排查几个角度把这套东西讲透。适合两类人看一类是想在ARM设备上玩Windows游戏但不想折腾太多底层配置的玩家另一类是想理解FEX-Emu Wine DXMT这套组合拳到底怎么协作的技术爱好者。我会尽量把每个环节的为什么讲清楚而不是只丢一堆命令让你抄。2. FEX-Emu、Wine、DXMT三层架构到底各管什么2.1 指令集翻译层FEX-Emu的工作机制要理解FEX-Emu先得理解一个基本事实ARM64和x86-64是两套完全不同的指令集。x86-64的指令变长、寻址模式复杂、有大量的隐式行为ARM64的指令定长、寻址模式规整、行为更显式。这意味着你不能简单地做一对一映射很多x86指令需要翻译成多条ARM指令才能等价实现。FEX-Emu的做法是动态二进制翻译。程序运行时它把x86-64的代码块翻译成ARM64的代码块翻译结果会缓存起来下次执行同一段代码就直接用缓存。这个缓存机制很关键因为翻译本身是有开销的如果每次都重新翻译性能会惨不忍睹。实际使用中FEX-Emu的翻译缓存在第一次运行某个程序时会比较慢但后续启动会明显加快这就是缓存生效的表现。这里有个容易被忽略的点FEX-Emu不只是翻译指令它还要模拟x86的内存模型。x86是强内存模型ARM是弱内存模型这意味着多线程程序在ARM上可能会出现x86上不会出现的内存可见性问题。FEX-Emu需要在翻译时插入适当的内存屏障指令来保证语义正确。这个开销是隐性的但确实存在也是为什么某些多线程密集的程序在翻译层下性能下降更明显的原因之一。2.2 Windows API兼容层Wine的角色边界Wine做的事情简单说就是用Linux/Unix的系统调用去实现Windows API。比如Windows程序调用CreateFileWine会把它转换成对应的POSIXopen调用程序调用MessageBoxWine会用自己的窗口系统画一个出来。它不模拟Windows内核而是重新实现了一套兼容的API。这就带来一个重要的认知Wine的兼容性取决于API覆盖度。一个Windows程序用到的API如果Wine都实现了它就能跑如果用到某个Wine没实现的冷门API就会报错或者行为异常。这也是为什么有些程序在Wine下完美运行有些却怎么都跑不起来——不是Wine不行而是那个程序恰好踩到了未实现的API。在Madeira这个场景里Wine还承担了一个额外任务它需要和FEX-Emu配合。因为Wine本身也是x86-64的程序它自己也要被FEX-Emu翻译。这就形成了一个有趣的嵌套FEX-Emu翻译WineWine再去加载和运行Windows程序而Windows程序的指令同样要被FEX-Emu翻译。这个嵌套层次如果配置不当性能损耗会成倍增加。2.3 图形翻译层DXMT如何把D3D变成MetalDXMT是这套链路里最年轻也最关键的组件。它的任务是把Windows游戏使用的Direct3D 11/12调用翻译成Apple的Metal API。为什么不用现成的方案因为之前主流的做法是通过DXVK把D3D转成Vulkan再通过MoltenVK把Vulkan转成Metal。这条链路多了一层转换开销更大而且MoltenVK对某些Vulkan特性的支持并不完整。DXMT选择直接翻译到Metal理论上少了一层中间环节延迟更低、特性映射更直接。但代价是它需要自己实现D3D到Metal的完整映射工作量大而且Metal本身和D3D的设计哲学有差异某些D3D的特性在Metal里没有直接对应需要绕路实现。实际使用中DXMT对D3D11的支持相对成熟D3D12的支持还在完善中。如果你玩的游戏是D3D9时代的可能需要走DXVKD3D9的路径如果是较新的D3D12游戏DXMT可能是唯一选择但要做好遇到渲染错误的心理准备。组件职责关键依赖常见问题FEX-Emux86-64到ARM64指令翻译翻译缓存、内存模型模拟多线程性能下降、首次启动慢WineWindows API到POSIX实现API覆盖度、注册表模拟冷门API缺失、字体渲染异常DXMTD3D到Metal图形翻译Metal特性映射着色器编译错误、纹理格式不支持3. 在ARM设备上把Madeira跑起来环境准备与安装3.1 系统环境的前置检查在动手之前有几项系统层面的东西必须先确认。首先是内核版本FEX-Emu对内核有要求因为它依赖一些特定的系统调用和内存管理特性。一般来说5.15以上的内核比较稳妥太老的内核可能缺少必要的支持。你可以用uname -r看一下当前内核版本。其次是文件系统Wine的prefix目录建议放在ext4或btrfs上不要放在网络文件系统或者某些对大小写不敏感的文件系统上。Wine内部有些程序依赖大小写敏感的文件名行为放在不敏感的文件系统上会出现找不到文件的问题。第三是内存这套东西对内存的消耗比原生运行要高。FEX-Emu的翻译缓存、Wine的prefix、DXMT的着色器缓存加起来会占用不少空间。建议至少留出10GB以上的可用空间内存方面8GB是底线16GB会更从容。提示如果你用的是Apple Silicon的Mac还需要确认是否开启了允许运行未签名内核扩展的设置某些图形相关的组件可能需要额外的权限。3.2 FEX-Emu的安装与RootFS配置FEX-Emu的安装有两种方式从发行版仓库安装或者从源码编译。对于大多数用户我建议优先用仓库版本因为编译FEX-Emu需要配置交叉编译环境比较折腾。以Debian/Ubuntu系为例可以添加FEX-Emu的官方仓库然后apt安装。安装完成后关键的一步是准备RootFS。FEX-Emu需要一个x86-64的根文件系统里面包含Wine和它依赖的库。这个RootFS可以是一个目录也可以是一个镜像文件。我个人的习惯是用目录形式方便直接进去改配置。RootFS的获取有几种途径可以用debootstrap创建一个最小的x86-64 Debian系统也可以直接用别人做好的RootFS压缩包。自己用debootstrap创建的好处是干净、可控缺点是耗时用现成的好处是快缺点是可能夹带一些你不需要的东西。创建好RootFS后需要把Wine装进去。这里有个细节Wine的版本选择很重要。太老的版本对新游戏支持不好太新的版本可能引入新的bug。我一般建议用Wine 8.x的稳定版或者用Wine-GE这类针对游戏优化的分支。# 示例用debootstrap创建x86-64 RootFS sudo debootstrap --archamd64 bookworm /path/to/rootfs http://deb.debian.org/debian # 进入RootFS安装Wine sudo chroot /path/to/rootfs apt update apt install -y wine wine64 winetricks3.3 DXMT的编译与部署DXMT的部署是整套流程里最容易出问题的一步。它需要和Wine的版本匹配因为DXMT是作为Wine的一个模块加载的接口对不上就会加载失败。所以你在编译DXMT之前要先确认你的Wine版本然后checkout对应版本的DXMT源码。编译DXMT需要Metal的开发工具链在macOS上就是Xcode的命令行工具。编译过程中最常见的错误是头文件找不到这通常是因为Xcode的路径没有正确配置。可以用xcode-select -p确认路径如果不对就用xcode-select --switch切换。编译完成后生成的.so或.dylib文件需要放到Wine的对应目录下。具体位置取决于你的Wine是怎么装的一般在lib/wine/x86_64-windows/或者类似的路径下。放好之后还需要在Wine的注册表里设置DLL覆盖让Wine优先加载DXMT而不是自带的D3D实现。# 设置DLL覆盖让Wine使用DXMT WINEPREFIX/path/to/prefix wine reg add HKCU\Software\Wine\DllOverrides /v d3d11 /t REG_SZ /d native /f WINEPREFIX/path/to/prefix wine reg add HKCU\Software\Wine\DllOverrides /v dxgi /t REG_SZ /d native /f注意DLL覆盖设置错了会导致Wine完全无法启动图形程序。如果设置后出现黑屏或崩溃先把覆盖删掉确认Wine本身能跑再重新配置。4. 跑起来之后才是真正的开始性能调优与兼容性打磨4.1 翻译缓存的预热与持久化FEX-Emu的翻译缓存默认可能是存在内存里的这意味着每次重启程序都要重新翻译。对于大型游戏这个预热过程可能长达几分钟体验很差。解决办法是开启缓存的持久化把翻译结果写到磁盘上下次启动直接读。FEX-Emu有相关的配置项来控制缓存行为具体参数名可能随版本变化但核心思路是设置一个缓存目录并确保它有足够的空间。缓存文件可能会很大一个大型游戏的缓存轻松上GB所以要预留空间。另外缓存的命中率和程序的执行模式有关。如果程序的行为很随机比如每次运行都走不同的代码路径缓存命中率就低加速效果有限。相反如果程序的主循环很固定缓存命中率就高第二次启动会快很多。这也是为什么有些游戏第一次卡第二次就流畅了。4.2 Wine prefix的精细化配置Wine的prefix里有一堆可以调的参数调好了能解决不少兼容性问题。我挑几个最常用的说。Windows版本模拟Wine可以模拟不同版本的Windows有些程序会检查系统版本版本不对就拒绝运行。用winecfg可以切换一般设成Windows 10比较通用。字体替换Wine自带的字体和Windows的字体不完全一样有些程序依赖特定字体找不到就显示乱码或者方块。解决办法是把Windows的字体文件复制到Wine的字体目录或者在注册表里做字体替换。中文乱码问题很多时候就是字体没配好。DLL覆盖前面提到过某些DLL需要用原生的从Windows复制过来的而不是Wine自带的因为Wine的实现可能有bug或者缺少功能。常见的需要覆盖的DLL包括msvcp140、vcrun2019相关的库等。用winetricks可以方便地安装这些运行库。# 用winetricks安装常用运行库 WINEPREFIX/path/to/prefix winetricks vcrun2019 dotnet48 corefonts4.3 DXMT的着色器编译与卡顿缓解DXMT在第一次遇到新的着色器时需要编译编译过程会导致卡顿。这个现象在D3D12游戏里尤其明显因为D3D12的着色器种类更多、编译更复杂。缓解办法是预编译着色器缓存有些游戏支持在加载时预编译有些则需要靠DXMT自己的缓存机制。DXMT的着色器缓存一般在prefix的目录下可以定期清理旧的缓存来释放空间但清理后下次运行又要重新编译。所以除非空间实在不够不建议频繁清理。另一个影响流畅度的因素是分辨率。在ARM设备上GPU的性能通常不如同代的独显所以适当降低分辨率和画质设置是必要的。我一般建议先从720p或者设备原生分辨率的一半开始试跑顺了再往上调。调优项推荐设置影响FEX-Emu缓存开启持久化预留5GB减少重复翻译开销Wine Windows版本Windows 10提高程序兼容性字体复制Windows字体到prefix解决中文乱码DXMT分辨率从720p起步平衡画质与帧率着色器缓存保留不频繁清理减少编译卡顿5. 那些让人抓狂的故障从现象到根因的排查链路5.1 程序启动即崩溃先分清是哪一层的问题程序双击后闪退这是最常见也最难查的问题。我的排查思路是逐层隔离先确认FEX-Emu本身能不能跑简单的x86-64程序再确认Wine能不能跑简单的Windows程序最后才怀疑DXMT。具体做法是在RootFS里直接跑一个x86-64的Linux命令行程序比如uname -m看FEX-Emu是否正常工作。如果这一步就失败问题在FEX-Emu的配置或者RootFS的完整性。如果这一步正常再跑wine notepad看Wine能否启动。notepad是最简单的Windows程序如果它都跑不起来问题在Wine的配置。如果notepad正常再跑目标程序这时候问题才可能出在DXMT或者程序本身的兼容性上。这个逐层隔离的方法能帮你快速定位问题所在的层避免在错误的方向上浪费时间。5.2 图形相关的黑屏与花屏黑屏和花屏基本可以锁定在DXMT或者Metal驱动层。先检查DXMT是否正确加载可以在Wine的调试输出里看有没有DXMT相关的日志。如果DXMT没加载检查DLL覆盖设置和DXMT文件的路径。如果DXMT加载了但还是黑屏可能是着色器编译失败。DXMT在编译着色器时如果遇到不支持的特性可能会静默失败导致画面出不来。这种情况可以尝试降低游戏的画质设置关掉一些高级渲染特性看是否能绕过。花屏则可能是纹理格式或者渲染目标格式不匹配。Metal对某些像素格式的支持和D3D不一样DXMT需要做转换转换过程中如果出错就会花屏。这种问题通常需要等DXMT更新修复用户层面能做的有限。5.3 中文乱码与字体缺失中文乱码是Wine环境下的经典问题根因是字体缺失或者字体映射不对。Wine默认的字体配置里中文字体可能指向了一个不存在的字体或者指向了一个不含中文字形的字体。解决办法分两步第一步是把中文字体文件比如simsun.ttc、msyh.ttf复制到Wine的字体目录通常在drive_c/windows/Fonts/下。第二步是在注册表里配置字体替换把Wine默认使用的字体映射到刚复制进去的中文字体。# 复制字体到Wine prefix cp /path/to/simsun.ttc /path/to/prefix/drive_c/windows/Fonts/ # 注册字体替换 WINEPREFIX/path/to/prefix wine reg add HKCU\Software\Wine\Fonts\Replacements /v MS Shell Dlg /t REG_SZ /d SimSun /f提示字体替换的注册表项可能因Wine版本而异如果上面的不生效可以试试用winetricks corefonts安装基础字体后再手动补充中文字体。5.4 性能突然下降的几种可能用着用着突然变卡这种问题往往比一开始就卡更让人困惑。常见的原因有几个翻译缓存被清理了导致重新翻译内存不足系统开始换页GPU过热降频ARM设备的散热通常不如台式机长时间高负载会触发降频。排查的时候可以先看系统内存和交换分区的使用情况再看CPU和GPU的温度和频率。如果是散热问题适当降低画质或者限制帧率能缓解。如果是内存问题关掉一些后台程序或者增加交换空间。6. 关于Madeira这类项目的一些个人判断我跟踪FEX-Emu Wine DXMT这条技术路线有一段时间了说几点自己的观察。这套方案目前的成熟度用一句话概括就是能跑但离省心还有距离。FEX-Emu的指令翻译已经相当可靠大部分x86-64程序都能跑起来Wine的API覆盖度也足够应付大多数游戏DXMT是短板D3D12的支持还在追赶遇到渲染问题基本只能等更新。另一个感受是这套方案的性能天花板受限于硬件。ARM设备的CPU单核性能和多核调度和x86还有差距GPU的驱动成熟度也不如桌面独显。所以即使软件层做得再好帧率也不可能和原生x86独显比。心态上要把它当成能玩而不是玩得爽。最后一点这类项目的迭代速度很快今天能跑的游戏明天可能因为某个组件更新就跑不了了反过来也一样。所以遇到问题先别急着下结论去项目的issue区看看有没有人遇到同样的问题往往能找到临时的解决办法。我自己就遇到过好几次昨天还好好的今天就不行了最后发现是某个组件自动更新到了不兼容的版本回滚就好了。如果你也在折腾这套东西我的建议是把每个组件的版本固定下来不要盲目追新。等确认新版本稳定了再升级能省掉很多莫名其妙的故障排查时间。
返回列表