新显卡绘制调用时在nvoglv32.dll崩溃

3

几天前,我更换了电脑硬件并安装了新的Windows 8系统。其中之一是将Radeon HD 7870显卡更换为Nvidia GTX 660。

重新设置Visual Studio 11后,我从Github下载了我的最新OpenGL项目并重建了整个项目。我从Visual Studio运行应用程序时出现了崩溃,原因是nvoglv32.dll

在Application.exe中(偏移量0x5D9F74E3)未经处理的异常:0xC0000005: 访问地址0x00000000时发生访问冲突。

在旧环境中,应用程序按预期工作。我没有更改项目或源代码的任何内容。唯一的区别是Visual Studio安装的语言,现在是英语,以前是德语。因此,我创建了一个新项目,并采用了所有设置,但错误仍然存在。

为了定位崩溃,我注意到所有初始化(窗口、着色器等)都成功了,错误出现在绘制调用glDrawElements()处,它指向我的延迟渲染器的几何通道。

经过一些研究,我发现nvoglv32.dll来自Nvidia,与名为Compatible OpenGL ICD的服务有关。这是否意味着我的应用程序运行在兼容模式下?那听起来像是一种支持旧应用程序的模式,而我希望我的应用程序在常规模式下运行!顺便说一句,我安装了最新的显卡驱动程序。

老实说,我不知道如何解决这个崩溃问题。它可能的原因是什么,如何解决?

更新:我在Geforce论坛上找到了一个关于我的问题的帖子。虽然没有回复,但作者通过更改两个OpenGL调用的顺序来解决了问题。

Hi all,

After poking around with my application source code for a few hours, I found that calling the functions...

glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, #)
glBindVertexArray(#)

...in that order causes the crash in nvoglv64.dll. Reversing the order of these calls to...

glBindVertexArray(#)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, #)

...prevents the crash and appears to be well-behaved.

Cheers, Robert Graf

由于我不使用顶点数组,所以我无法简单地进行此修复,但可能存在类似的问题。我将报告我的进度。

更新:我完全不知道如何解决我的问题。我尝试了不同的视频驱动程序版本,但没有任何区别。我完全重写了渲染器,使用最小的着色器和简单的前向渲染。但崩溃仍在第一个绘制调用时发生。


我从显示器切换到电视后开始遇到这个问题。 - Khlorghaal
2个回答

4
为了找到崩溃原因,我注意到所有初始化(窗口、着色器等)都成功了,错误出现在绘制调用glDrawElements()中。
很可能你的代码一直存在越界访问,但是AMD Radeon Catalyst驱动程序预留了更多的地址空间,或者先行捕获了它们。而现在你的NVidia GeForce驱动程序没有这样做。
要么你传递给glDrawElements一个太大的数字来绘制元素,要么你的索引缓冲区包含超出顶点数组范围的索引值。如果是后者,则你可能正在使用客户端顶点数组,因为VBO通常会捕获越界访问;此外,它们不会使你的客户端程序崩溃,而只会渲染垃圾数据。

1
我想找出是否存在越界访问,但我不知道它可能来自哪里。我专门为我的网格使用VBOs。在开发的早期阶段,我遇到了你描述的问题,没有崩溃,但它只是渲染垃圾,但这个问题应该在一段时间前就解决了。今天,我使用这行代码计算每帧要绘制的元素数量。int count; glGetBufferParameteriv(GL_ELEMENT_ARRAY_BUFFER, GL_BUFFER_SIZE, &count); glDrawElements(GL_TRIANGLES, count/sizeof(GLuint), GL_UNSIGNED_INT, 0); - danijar
1
@sharethis:通常的做法是逐个禁用有问题的程序路径,直到错误消失。预处理器中的 #ifdef 语句在这里非常有用。一旦找到有问题的程序路径,就要逐步单步调试每一个操作。还要在文件中写入大量的调试日志,记录涉及的每个变量和计算,并保持非缓冲写入访问权限。 - datenwolf
我在我的引擎中遇到了完全相同的问题。在Nvidia驱动程序设置中禁用“线程优化”可以消除错误。我打赌这是一个驱动程序错误。 - Tara
@Dudeson:很有可能,但是你可以通过使用不同的OpenGL实现来验证,甚至可以尝试使用一些软件实现比如Mesa,看看是否也会在那里崩溃。 - datenwolf
@Datenwolf:我只在一些Nvidia显卡上遇到了这个问题。在ATI和Intel显卡上运行良好。我试图分离问题,但是我没有看到任何可能导致它的因素。 - Tara
显示剩余8条评论

1

最终我想出了一种解决崩溃的方法。

我使用的SFML框架用于创建窗口和其他功能,提供了一个函数来重置上下文的OpenGL状态。我在窗口创建后立即调用它。

尽管我无法解释为什么,但是删除该函数调用解决了崩溃问题。也许是因为GLEW或其他东西还没有初始化那一刻。

sf::RenderWindow window;
window.create(VideoMode(1024, 768), "Window Title");
window.resetGLStates(); // removing this line fixed the crash
window.setVerticalSyncEnabled(true);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接