在我们游戏的一些最终用户的错误报告中,我经常看到以下行为:IDirect3DVertexBuffer9::Lock
失败,返回的错误代码是D3DERR_NOTAVAILABLE
.
一旦发生这种情况,通常(但不总是)紧随其后的是CreateTexture
orCreateVertexBuffer
调用失败并出现错误D3DERR_OUTOFVIDEOMEMORY
。
顶点缓冲区锁定失败的可能原因是什么?虚拟内存地址空间是否会耗尽,或者什么?
根据来自 Microsoft 的 Chuck Walbourn 的 DIRECTXDEV 响应,除了“地址空间不足”之外,另一个原因可能是“页面池不足”。
或者,在 Windows XP 上,这可能表明您已达到分页池内核内存的限制。通常,当您创建大量 Direct3D 资源(纹理等)时会发生这种情况。
我们确实创建了很多 Direct3D 资源。
这是我发布到 DirectXDev 的内容:;)
您是否检查过您的应用程序使用了多少内存?(请务必在任务管理器中选择虚拟内存列!)。我的猜测是基于内存碎片的问题,如您所建议的,会导致您耗尽地址空间。
但是,它可能是驱动程序错误...
调试运行时是否提供任何有用的信息?
编辑:我唯一能想到的另一件事是光圈内存已经用完了。我不知道这如何与 PCIExpress 一起工作,但在 AGP 上你可以设置光圈大小。但是,我不知道如何检查它是否已满。我怀疑您看到的错误是报告它已满。您是否正在使用 Discard 标志进行大量锁定?如果是这样,它们可能会在光圈中创建大量新分配,并导致您在那里的内存不足。然而,这纯粹是猜测工作。
我猜想如果这种情况只发生在您的一些用户身上,那就是低端机器上的用户。如果事情运行缓慢,那么您最终可能会在命令缓冲区中缓冲大量数据。这将使控制滞后,并且“可能”会导致您看到的问题。您可能想尝试确保命令缓冲区永远不会太长。如果您确保在没有丢弃标志(即标志设置为 0)的情况下完成每一帧的第一次锁定,那么这将导致管道停止,直到顶点缓冲区被渲染并使命令缓冲区与您恢复同步。这将导致速度变慢,因为命令缓冲将无法轻松消除帧速率峰值......
无论如何......这只是一个猜测!
关于内存不足的问题是有效的。我们需要一些关于 Lock() 调用的细节来确定,但是例如,如果它在 DEFAULT 池中并且它是动态的(通过了 D3DLOCK_DISCARD 标志),那么您的驱动程序很可能会尝试找到一块未使用的内存来返回(因为它内部有两倍或三倍的缓冲区)并失败,因为您很快就会发现自己的视频内存已耗尽。