超出DirectX11视频内存

时间:2017-02-10 00:23:41

标签: c++ memory directx-11 direct3d

我有一个渲染循环,用于侦听手写板输入并从顶点/索引缓冲区(以及其他内容)中绘制。顶点数据可以增长,当它达到一定水平时,DispatchMsg(& msg)遇到这个:

Unhandled exception at 0x5DDBDEF0 (msvcr110d.dll) in App.exe: 0xC0000005: Access violation writing location 0x00000000.

场景中分配的顶点和索引缓冲区的总大小每次都大致相同:

Total Vertices count: 10391370
Total Indices count: 41565480
Total Vertices size: 249392880 (bytes)
Total Indices size: 997571520 (bytes)

并在另一个抽样中:

Total Vertices count: 9969300
Total Indices count: 39877200
Total Vert size: 239263200
Total Indices size: 957052800

顶点和索引缓冲区都是D3D11_USAGE_DEFAULT。场景中的总大小分配高于上面列出的,但较小的缓冲区经常被释放。最后在顶点/索引缓冲区中也有一些填充。

每次(当达到异常时)即将发送的消息是581,我相信可能是:

#define WM_POINTERUPDATE                0x0245

我真的不介意场景缓慢渲染,但是如果我达到了一些最大的内存分配(视频内存?),那么内存有一种方法可以以速度为代价慢慢地向/从maim内存寻呼?我尝试禁用draw()调用,该调用调用像素,顶点着色器和绘图调用,但仍然会发生异常。我更喜欢速度权衡或异常处理。

2 个答案:

答案 0 :(得分:1)

找到答案并解决问题。根据我的输入顶点计数,CreateBuffer失败或malloc / HeapAlloc失败。

我仍然不能100%确定GPU是否应该在某个点之后将内存分页到主系统内存,或者这是不可避免的,因为场景数据必须在每个帧期间保留在GPU内存上计算(深度,照明等),但我想A)只有当我手动解除分配/重新分配缓冲区(无论如何都会很慢)和B)alloc的大小时,才可能进行分页。 ; ed缓冲区(顶点,索引..)是问题,而不是它们的每帧计算。

我尝试切换到其他缓冲区用法(USAGE_DYNAMIC),但分配失败仍然发生在同一级别。

我对缓冲区大小(需要填充的缓冲区)进行了快速更改,现在至少有2000万个顶点。我的GPU已经很老了,所以不错,不过有些渲染器可以远远超出这个,我知道。

专注于解决方法并尽可能减少细节。我认为我可以通过细分获得大约15倍的细节,所以不是很糟糕。

如果有人有任何更多的见解,可以转换你的正确答案,但不确定我是否会采取另一条路径。

答案 1 :(得分:1)

从您问题中的数字来看,您似乎为顶点和索引数据(约1.2GB)分配了大量内存。如果您的应用程序是32位(x86,而不是x64),它只能访问2GB的内存,因此很可能是您的进程内存不足。

GPU可以访问部分系统内存(与GPU内存相比速度相当慢,但完全没有内存)。例如,对于NVidia GPU,NVidia控制面板显示在"系统信息" > "共享系统内存&#34 ;;这通常是系统中RAM总量的一半。据我所知,这个系统内存占用了你的一部分过程'地址空间。

如果你的年龄很大" GPU拥有512MB内存,需要大约768MB的额外系统内存才能满足您的内存需求。这为您的应用程序留下了1.2GB。我猜你的应用程序试图在数组中分配1.2GB的系统内存,这将占用你想要上传到GPU的几何数据。这恰好适合,但您的应用程序代码也需要在某个地方。在这个假设的情况下,你已经用完了内存。当然,一旦你将几何数据上传到GPU,就可以摆脱系统内存阵列,但正是在这个时刻,系统还没有足够的内存来创建GPU的内存缓冲区。您要求的尺寸。

将项目切换为64位(在Visual Studio中为x64)将使您的进程占用更多内存(在大多数情况下,直到系统和页面文件中可用的内容),并解决您的问题。问题。如果内存限制实际上是问题。

另一件事:我注意到 - 假设你的数字是正确的 - 你为索引缓冲区的每个索引分配24个字节,就像你为顶点缓冲区中的每个顶点分配的那样多。那是对的吗?索引(它只是顶点缓冲区的偏移量)不应大于4个字节。您是否真的尝试分配实际需要的GPU内存的6倍,还是在应用程序中误算?

如果您快速释放然后在GPU上重新创建一个缓冲区,那么D3D可能会保留旧的"缓冲一段时间(至少只要它仍然绑定到GPU管道),因此它可能会因为内存而内存不足。因此,实际取消绑定您即将发布的缓冲区(通过调用IASetVertexBuffers(NULL, 0, 0, 0, 0)IASetIndexBuffer(NULL, DXGI_FORMAT_R16_UINT, 0))可能有所帮助。