☰
D2DX架构全景:Glide API到DirectX 11转译引擎的设计哲学与核心组件
2026/9/25 1:33:17 网站建设 项目流程

D2DX架构全景:Glide API到DirectX 11转译引擎的设计哲学与核心组件

【免费下载链接】d2dxD2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions.项目地址: https://gitcode.com/gh_mirrors/d2/d2dx

D2DX 是让《暗黑破坏神2》在 modern PC 上流畅运行的完整解决方案——它模拟 3dfxGlide 图形 API,把游戏的全部绘制调用转译成DirectX 11指令,从而带来高帧率、宽屏与抗锯齿支持。本文将从架构视角拆解这个"Glide 到 DirectX 11 转译引擎"的三层设计与核心组件,帮助你理解它如何在 20 年前的老游戏与现代显卡之间架起桥梁。

一分钟看懂 D2DX:一个"假显卡驱动" 🎮

《暗黑破坏神2》当年使用 3dfx 的 Glide API 直接驱动显卡,而今天的显卡早已不再支持这套接口。D2DX 的做法是:向游戏提供一个名为glide3x.dll的假 Glide 驱动,骗过游戏;游戏以为自己在调用真正的 Glide,实际上每个调用都被转发进 D2DX 的转译引擎,最终以 DirectX 11 的形式渲染到窗口或全屏中。

游戏内效果则如右图所示:原始 640×480 的画面被高质量放大到现代 1080p 显示器上,细节依然锐利。

三层架构:一条清晰的调用链

D2DX 的源码位于 src/d2dx/,整体分为三层,职责泾渭分明:

游戏进程 (d2game.exe) │ 调用 grDrawVertexArray / grBufferSwap ... ▼ ① Glide 层 glide3x.cpp ────── 实现全部 Glide API 入口,纯转发 │ 通过 D2DXContextFactory 单例获取上下文 ▼ ② 转译层 D2DXContext ─────── 维护 Glide 状态机,把调用组装成"批次(Batch)" │ 同时处理 Win32 拦截与游戏内存探测 ▼ ③ 渲染层 RenderContext ───── DirectX 11 设备/交换链、着色器、缩放输出

这种"入口层只做转发、逻辑集中在上下文"的设计,让每一层都可以独立测试(项目自带单元测试工程 d2dxtests/),也方便第三方 MOD 接入。

第一层:glide3x.dll —— Glide API 的"假驱动"

入口实现在 glide3x.cpp,它用 C 风格导出了一整套 Glide 函数:grSstWinOpen(开窗口/全屏)、grVertexLayout(定义顶点格式)、grDrawVertexArrayContiguous(批量提交顶点)、grBufferSwap(交换帧缓冲)等。

每个函数内部都遵循同一个套路——以 grDrawVertexArrayContiguous 为例:

  • 用_ReturnAddress()取回调用方返回地址,交给上层用于判断"这帧画的是游戏还是菜单";
  • 转发给 D2DXContextFactory::GetInstance() 返回的单例上下文;
  • 用try/catch包裹一切异常,保证游戏进程绝不崩溃。

还有一些"聪明"的兼容细节:例如 grLfbLock 只为游戏真正会用到的 640×480 RGBA 写锁模式分配内存,其余调用一律返回"不支持",最大限度贴近原始驱动行为。

第二层:D2DXContext —— 状态机与批次组装

核心类 D2DXContext 实现了三个接口(见 ID2DXContext.h):

接口职责
IGlide3x响应全部 Glide 调用(OnDraw*、OnTexSource、OnGammaCorrectionRGB…)
IWin32InterceptionHandler拦截SetCursorPos、Sleep等 Win32 调用
ID2InterceptionHandler拦截游戏内部文字/图块绘制,服务运动预测

它的工作方式很像一个迷你状态机:

  1. 纹理内存模拟:维护一块虚拟 TMU 显存(GlideState::tmuMemory),游戏的grTexDownloadMipMap把像素"下载"到这里,grTexSource指定纹理地址;
  2. 批次(Batch)组装:每次grDrawVertexArray*调用都会按当前混合/颜色模式归入 Batch,相同状态的顶点被合并提交,减少状态切换开销;
  3. 帧循环:OnBufferSwap触发整帧绘制,此时依次执行纹理哈希、运动预测修正、批次提交;
  4. 能力协商:通过 Feature 标志位声明当前游戏版本支持哪些增强(单位/文字/天气运动预测),实现"特性降级"而非整体失效。

第三层:RenderContext —— DirectX 11 渲染管线

RenderContext 负责所有与显卡打交道的事:创建ID3D11Device与IDXGISwapChain(成员定义),并实现了多套策略化的同步与交换方式——AllowTearing(无垂直同步、最低延迟)、Interval0/1、以及基于ID3D11DeviceContext1::SetFrameLatencyWaitableObject的帧延迟控制,这就是它"低延迟全屏"的来源。

画面输出阶段由一组 HLSL 着色器完成(src/d2dx/ 下均为独立文件):

  • DisplayIntegerScalePS.hlsl:整数倍缩放,保持像素锐利;
  • DisplayNonintegerScalePS.hlsl:非整数缩放,采用"抗锯齿最近邻"采样避免糊化;
  • DisplayCatmullRomScalePS.hlsl 与 DisplayBilinearScalePS.hlsl:偏柔和观感的可选滤镜;
  • GammaPS.hlsl:实现正确 gamma 校正,保证暗部细节。

纹理缓存:FNV 哈希 + 位图 PMRU 淘汰

Glide 把纹理下载到"显存"再采样,而 D2DX 需要把它们变成 D3D11 纹理供着色器使用。TextureCache 用**固定尺寸的四张纹理图集(atlas)**存放所有游戏纹理:

  • 内容键由 TextureHasher 基于FNV1a 哈希(第三方实现见 thirdparty/fnv/)计算,避免重复纹理占用空间;
  • 淘汰策略不是简单的 LRU,而是自定义的 位图 PMRU(probabilistic MRU),对"反复使用的 UI 纹理"与"一次性场景纹理"都有更优的命中率;
  • 图集满时自动按策略驱逐旧纹理,整帧开始还会调用OnNewFrame刷新访问统计。

高帧率秘密:三套运动预测器 🚀

原版游戏锁定 25 FPS,直接解锁帧率只会得到"跳帧"。D2DX 的思路是在渲染层插值位置——既然游戏逻辑每 25ms 更新一次单位坐标,那在中间帧里按速度外推即可。对应三个组件:

  • UnitMotionPredictor:追踪每个单位的lastPos → velocity → predictedPos(见 UnitMotion 结构),实现人物、怪物、投射物、阴影的平滑移动;
  • TextMotionPredictor:跟随滚动的伤害数字等文字;
  • WeatherMotionPredictor:雨雪天气粒子。

配合 GameHelper 对游戏内存的 FPS 补丁(TryApplyInGameFpsFix、TryApplyMenuFpsFix)和睡眠修复,菜单与游戏内都可以稳定跑在 60 FPS 以上。

Win32 拦截与内存探测:Detours 的功劳

D2DX 借助微软 Detours 库(封装在 Detours.cpp)挂钩两类入口:

  1. Win32 API:拦截Sleep消除卡顿微停顿、拦截SetCursorPos把鼠标约束在窗口内(OnSetCursorPos);
  2. 游戏内部函数:通过返回地址匹配(IdentifyGameAddress)定位文字/图块绘制函数,为运动预测提供每帧真实坐标。

此外 CompatibilityModeDisabler 会主动阻止 Windows XP 兼容模式(它会导致画面花屏),体现了"现代环境跑老游戏"的设计立场。

与第三方 MOD 协作:ID2DXConfigurator 接口

D2DX 还暴露了一个类 COM 的公开接口 ID2DXConfigurator,供高分辨率 MOD 调用:

  • SetCustomResolution(w, h):告知 D2DX 使用自定义游戏分辨率,内置宽屏 MOD 自动让位;
  • GetSuggestedCustomResolution():获取与显示器比例匹配的推荐分辨率。

这是典型的开闭设计:核心行为可被外部扩展覆盖而不需修改 D2DX 本身。分辨率 MOD 的底层则内嵌了 SGD2FreeRes(以 lzma 压缩打包,运行时经 pocketlzma 解压),由 BuiltinResMod 加载。

画质开关:FXAA 与宽屏选项

抗锯齿由 FXAA 实现(基于 Timothy Lottes 的公开实现),只作用于锯齿明显的边缘,不破坏像素风。对比效果如下:

全部行为都可通过配置文件 d2dx-defaults.cfg 定制(复制到游戏目录并改名为d2dx.cfg):

  • 窗口区段:scale=1-3整数缩放、position、frameless无边框窗口;
  • 游戏区段:自定义size与filtering(锐利 / 双线性 / Catmull-Rom);
  • 关闭项区段:nowide、noaa、nomotionprediction等可逐项回退到原版体验。

例如设置nowide=true后,标题画面会以约 4:3 的整数缩放模式呈现:

快速上手:获取与验证 📦

仓库为只读镜像,克隆后只需把编译产物glide3x.dll拷入《暗黑破坏神2》目录:

git clone https://gitcode.com/gh_mirrors/d2/d2dx

启动游戏时加参数-3dfx(Game.exe -3dfx),之后 ALT-Enter 即可在窗口与全屏间无卡顿切换。

小结:这套架构最值得学习的地方 ✨

  1. 边界清晰:Glide 入口层零逻辑,状态机与渲染器分层解耦,单测工程可直接验证批次、SIMD 与缓存逻辑;
  2. 策略化而非硬编码:缩放滤镜、同步策略、纹理淘汰均可配置/可替换;
  3. 渐进式增强:Feature标志 + 多版本适配(1.09d~1.14d),新特性默认开启又随时可关;
  4. 生态友好:ID2DXConfigurator让 D2DX 成为可被其他 MOD 编排的"渲染平台",而不只是一个独立的 MOD。

从 Glide 到 DirectX 11,D2DX 用不到两万行 C++ 证明了:理解旧 API 的每一处怪癖,就能让 25 年前的游戏在现代显卡上跑出它从未有过的流畅。

【免费下载链接】d2dxD2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions.项目地址: https://gitcode.com/gh_mirrors/d2/d2dx

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询