2

Checking OpenGL error state after OpenGL calls in debug builds can be an invaluable tool for finding bugs in OpenGL code. But what about errors like running out of memory when allocating textures or other OpenGL resources? What are the best practices on handling or avoiding errors like these?

An OpenGL resource allocation failure would probably be fatal in most cases so should a program just try to allocate a reasonable amount of resources and hope for the best? What kind of approaches are used in real world projects on different platforms, e.g., on PC and on mobile platforms?

4

2 回答 2

6

对此没有“一刀切”的方法。这完全取决于应用程序及其重要性。一般规则是:尽可能优雅和安全地失败。

在游戏的情况下,更可取的做法是保存当前游戏状态的快照(最好在关键点之前和之后添加自动保存点)终止游戏过程并向用户显示一个可以理解的原因失败; 如果有保存游戏,请向他保证他的进度不会丢失。

在医疗诊断系统的情况下,通知用户图形显示已损坏,并且他不得将当前在屏幕上可见的内容用于任何进一步的诊断目的。

在飞行控制器显示器、医疗系统或类似应用中不能选择完全故障的情况下,您的系统必须以这样一种方式构建,即任何部分故障,故障部分都将被隔离,并且有足够的冗余和备份操作可以正常开始。

例如,飞行控制器显示器不是由一台计算机提供的,但每个显示器都有(IIRC)三台独立运行的计算机,产生相同的输出,它们的编程不同,因此其中一台计算机的编程故障将导致与其他 2 台计算机的不一致。每台计算机将其内部状态输入仲裁器,以确保所有计算机都同意其数据。显示信号本身通过另一个独立的比较仲裁器馈送,该比较仲裁器比较显示输出,并且在出现故障时也会禁用有问题的系统输出。

于 2013-09-28T22:41:48.127 回答
6

如今,在为纹理和顶点缓冲区分配资源时内存不足的情况很少见。当您遇到这种情况时,您应该已经知道您正在接近系统要求的限制,并且有一个足够聪明的资源管理器来处理它。

在 PC 范围内,可用内存量变得越来越不相关,也越来越难以定义。纹理正在成为虚拟化资源,其中部分纹理仅在着色器中引用特定子区域时才被获取并存储在本地 (GPU) 内存中(OpenGL 4.4 术语中的稀疏纹理,或 D3D 11.2 术语中的平铺资源)。您可能还会听说此功能称为部分驻留纹理,这是我最喜欢使用的术语。

由于部分驻留纹理 (PRT) 是 DX 11.2+ PC 硬件上的一种架构趋势,并且是 Xbox One / PS4 的一项关键功能,因此可用内存量将越来越少,因为应用程序终止事件。当必须处理页面错误时(例如,第一次引用纹理的一部分的内存),这将更多地影响性能,并且必须注意尽量减少抖动。这与 10 年前的情况并没有太大的不同,只是纹理图集或 mipmap 级别中的单个图块可能具有不同的状态,而不是完全驻留或完全非驻留的纹理。处理内存故障的方式实际上可以为更高效的程序生成内容和从基于光学/网络的存储流式传输打开大门。

话虽如此,虚拟化内存资源并不是处理实时应用程序和/或嵌入式应用程序的最有效方式。通常需要额外的硬件来处理内存映射,并且在发出非常驻资源的内存获取时会引入额外的延迟。在移动领域,我怀疑 PRT 会发生很大的变化,在这里您仍然会受益于较低级别的内存管理以及纹理分配之前的代理纹理等东西;不幸的是,OpenGL ES 甚至不支持代理纹理。

您的资源管理器应设计为保留为所有类型的资源分配的内存的运行选项卡。它不会完全准确,因为 OpenGL 对你隐藏了很多细节,但它会给你一个大图景。您将能够立即看到,从 RGBA16F 渲染缓冲区切换到 RGBA8 可为您节省 X 多个字节的内存,或者从您的顶点缓冲区之一中消除 1 个顶点属性会改变存储要求。您可以在分配资源时插入自己的检查,并在运行时将它们作为断言失败等处理。更好地定义和监控你自己的阈值,而不是让 OpenGL 只在它不能满足内存请求之后才抱怨。

于 2013-09-28T22:42:00.740 回答