2017-02-10 75 views
1

我有一个渲染循环,用于监听手写板输入并从顶点/索引缓冲区(除其他之外)绘制。顶点数据可以成长,当它击中一定的水平,DispatchMsg(& MSG)遇到这样的:超过DirectX11视频内存

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 

我真的不介意的场景渲染慢,但如果我达到一些最大的内存分配(视频内存?)是否有一种方法让内存以速度的速度缓慢地往/从内存中寻址?我尝试禁用调用像素,顶点着色器和绘制调用的draw()调用,但仍然发生异常。我更喜欢速度折衷或解决例外。

+0

您绘制了多少个verticies?这似乎是很多数据。 1000万个顶点? – tadman

+0

正确,看起来很高,所以我在某个时间期待问题,只是想弄清楚原因或可以做些什么。 – user176692

+0

这是很多vert。我很惊讶你可以分配那么多没有东西着火。你是否创造了太多,就像是以某种方式泄漏它们? – tadman

回答

1

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

GPU可以访问系统内存的一部分(与GPU内存相比,速度非常慢,但比内存要好)。例如,对于NVidia GPU,NVidia控制面板在“系统信息”>“共享系统内存”下显示;这通常是系统中RAM总量的一半。据我所知,这个系统内存占用了你进程地址空间的一部分。

如果您的“漂亮的”GPU具有512MB的内存,则需要大约768MB的额外系统内存才能满足您的内存需求。这为您的应用程序留下了1.2GB。我猜你的应用程序试图在阵列中分配1.2GB的系统内存,这会将你想要上传到GPU的几何数据。这只适合,但你的应用程序代码也需要在某个地方。在这个假设的情况下,你已经用完了内存。当然,一旦将几何数据上载到GPU后,您可以摆脱系统内存阵列,但恰恰此时,系统没有足够的内存来创建您请求的GPU内存缓冲区。

将项目切换为64位(Visual Studio中的x64)将使您的进程占用更多的内存(大多数情况下可达系统和页面文件中的可用内存),并解决您的问题。如果内存限制实际上是问题。另一件事:我注意到 - 假设你的数字是正确的 - 你为索引缓冲区分配每个索引24个字节,就像你为顶点缓冲区中的每个顶点分配一样多。那是对的吗?索引(它只是顶点缓冲区的偏移量)不应大于4个字节。你是否真的试图分配6倍于你实际需要的GPU内存,还是在你的应用程序中错误计算?

如果快速释放并在GPU上重新创建缓冲区,那么D3D可能会将“旧”缓冲区保持一段时间(至少只要它仍然绑定到GPU管道),所以它可能会因为这个而失去记忆。所以它可能有助于实际解除您即将释放的缓冲区(通过调用IASetVertexBuffers(NULL, 0, 0, 0, 0)IASetIndexBuffer(NULL, DXGI_FORMAT_R16_UINT, 0))。

+0

指数分配可能已经关闭,但是每个顶点都被重新使用了很多,以构建金字塔或菱形的形状。这正在被控制点和细分或几何着色器替代以实现实时渲染,而球体则用于离线渲染。 32位地址空间是一个巨大的问题,谢谢你提到这一点,我完全忽略了这一点。我正在使用一些我建立的32位库,并且需要移植这些库。现在也使用W5100 Firepro,这也将扩展内存功能。 – user176692

+0

要明确一点,并不是索引数目似乎太高(重用索引FTW),而是索引占用的内存数量(字节数)。第一个示例中的41565480索引应该占用41565480 * 4 = 166261920个字节(166MB),但根据您的问题,将分配997571520个字节(997MB!),推动内存使用几乎肯定超过了32位进程的内存限制。由于指定的内存量是指数乘以24(这是您的顶点大小)的数量,因此您的索引缓冲区大小计算可能是错误的,或者只是一个错字。 – Pepor

+0

我这么认为!有没有这个评论,但不知道我使用的调试信息// debugMsg(“Ind size:”+ iToS(sizeof(Vertex)* editingModel-> builtIndicesCount));所以它分配得更少,只是在我的调试日志中显示不正确。已经使用控制点并改变了几何体的构建方式,但抓住了! – user176692

1

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

如果GPU在特定点之后应该将内存分页到主系统内存,或者这是不可避免的,因为在每帧计算期间场景数据必须保留在GPU内存中(深度,照明等),但我认为A)分页只有当我手动释放/重新分配缓冲区(反正会很慢)和B)分配的缓冲区(顶点,索引......)的大小是可能的这个问题,而不是它们上的每帧计算。

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

我对缓冲区大小(需要填充的缓冲区)进行了快速修改,现在至少有2000万个顶点。我的GPU非常老,所以这并不坏,尽管有些渲染器可以超越这个,我知道。

将重点放在解决方法,并尽可能减少细节。我认为我可以用tesselation获得约15倍的细节,所以不会变形。

如果任何人有更多的见解,可能会改变你的正确答案,但不知道我是否会采取另一条路。