将 32 位 directx9 应用程序转换为大地址感知

use*_*591 12 c++ x86 32-bit direct3d directx-9

当内存接近 2GB 时,我们遇到了旧的闭源游戏引擎无法编译着色器的问题。

问题通常与D3DXCreateEffect. 通常它会返回 HResult“内存不足”,有时会d3dx9_25.dll在弹出窗口中打印随机错误,或者它只是完全的段错误。

我相信问题在于缺乏大地址意识:我注意到其中一个d3dx9_25.dll崩溃做了一些暗示这样的事情。它需要一个看起来像 的有效指针0x8xxxxxx3,检查位0x80000003是否点亮,如果是,则位反转指针并取消引用它。结果指针指向未分配的内存。在编译前强制引擎 malloc 2GB 会使着色器每次都无法编译。

不幸的是,我们对 DX9 的了解非常有限,我已经看到 DX9 有一个标志,D3DXCONSTTABLE_LARGEADDRESSAWARE但我不确定它到底应该去哪里。我能找到的游戏使用的唯一 API 调用依赖于它D3DXGetShaderConstantTable,但问题发生在它被调用之前。注射标志(1 << 17) = 0x20000,以D3DXCreateEffect使着色器以另一种方式失败编译。

  1. D3DXCreateEffect应该接受较大的地址标志?我发现了一个使用它的wine 测试,但深入研究 DX9 程序集,它抛出的错误是由内部函数FFFFF800在设置了in 标志中的任何位时返回 HResult Invalid Call 引起的,这让我相信CreateEffect不应该接受这个标志.

  2. 在此之前还有其他地方我应该注入大地址感知标志吗?我知道D3DXGetShaderConstantTable需要修复对使用的调用D3DXGetShaderConstantTableEx,但它甚至还没有达到。

Chu*_*urn 6

LargeAddressAware 有点像黑客,所以它可能会也可能不会帮助你的情况。它仅在您的应用程序需要接近 2GB VA 的更多空间时才有帮助,如果需要更多空间,则没有帮助。

旧版 DirectX SDK Direct3D 9 时代效果系统的一个关键问题是,它假设效果“句柄”的高位是免费的,因此它可以使用它,而没有位的句柄是字符串的地址。此假设不适用于 LargeAddressAware。

要启用此功能,请D3DXFX_LARGEADDRESS_HANDLE在包含d3dx9.h标题之前进行定义。然后,您必须D3DXFX_LARGEADDRESSAWARE在创建所有效果时使用该标志。您不能使用别名技巧,您可以在所有效果方法上使用“字符串名称”而不是“句柄”。相反,您必须使用GetParameterByName来获取句柄并使用它。

我不记得LAA 标志是何时添加到 Direct3D 9 的效果中的。

如果您使用d3dx9_25.dll的是 2005 年 4 月发布的 DirectX SDK。如果您使用的是“Pixel Shader Model 1.x”,那么您不能使用任何比d3dx9_31.dll(2006 年 10 月)更新的版本——更高版本的 DirectX SDK 允许您使用D3DXSHADER_USE_LEGACY_D3DX9_31_DLL刚刚通过着色器编译传递到此场景的旧版本.

许多 32 位游戏会失败然后启用 LAA 的一个关键原因是虚拟内存碎片。改进您的 VA 内存布局可以使您的分配更加统一也有帮助。