【发布时间】:2021-01-26 20:00:26
【问题描述】:
当内存接近 2GB 时,我们遇到了旧的闭源游戏引擎无法编译着色器的问题。
问题通常出在D3DXCreateEffect。通常它会返回“内存不足”的 HResult,有时d3dx9_25.dll 在弹出窗口中打印随机错误,或者它只是彻底的段错误。
我认为问题在于缺乏大地址意识:我注意到其中一个 d3dx9_25.dll 崩溃正在做一些暗示这样的事情。它采用了一个看起来像 0x8xxxxxx3 的有效指针,检查了位 0x80000003 是否被点亮,如果是,它位反转指针并取消引用它。结果指针指向未分配的内存。在编译之前强制引擎 malloc 2GB 使得着色器每次都无法编译。
不幸的是,我们对 DX9 的了解非常有限,我看到 DX9 有一个标志 D3DXCONSTTABLE_LARGEADDRESSAWARE,但我不确定它到底应该去哪里。我能找到的游戏使用的唯一 API 调用依赖于它是 D3DXGetShaderConstantTable,但问题发生在它被调用之前。将标志(1 << 17) = 0x20000 注入D3DXCreateEffect 会使着色器以另一种方式编译失败。
-
D3DXCreateEffect是否应该接受大地址感知标志?我发现了一个wine test 使用它,但是深入研究DX9 程序集,它抛出的错误是由一个内部函数在设置标志中FFFFF800中的任何位时返回HResult Invalid Call 引起的,这让我相信CreateEffect不应该接受这个标志。 -
在此之前我还应该在其他任何地方注入大地址感知标志吗?我知道需要修复对
D3DXGetShaderConstantTable的调用才能使用D3DXGetShaderConstantTableEx,但它甚至还没有到达。
【问题讨论】:
-
您考虑过迁移吗?听起来您已经到了引擎可以合理支持的极限了。
-
我认为你搞错了。默认情况下,Windows 会安全播放它,并且不会将 >2GB 的指针传递给旧应用程序。这样,像指针否定之类的技巧的旧应用程序将继续工作。 “大地址感知”是一个标志,告诉 Windows“我没有做任何奇怪的事情,我可以处理 >2GB”。您可以分配 2GB 的事实意味着您的应用声称它是 LAA。
-
另外,我认为您可能会忽略
0x80000003中的“3”。这暗示了一个未对齐的指针。否定它不会使其对齐,但反转所有位会。 -
x86
neg是 2 的补码否定(从0中减去),C 一元-。 x86not是 1 的补码否定,翻转所有位,C~。我们称之为按位非,而不是否定,以区别于数学 / 2 的补码否定。 -
你说得对,我记错了。我再次检查,指令确实是
not。
标签: c++ x86 direct3d 32-bit directx-9