【问题标题】:How to remove unused resources from an OpenGL program如何从 OpenGL 程序中删除未使用的资源
【发布时间】:2015-04-28 16:27:20
【问题描述】:

我正在尝试为 OpenGL 创建类似效果系统的东西,并且我希望能够在同一个文件中定义多个着色器。但是我发现了以下问题。假设我有两个着色器:A 和 B。着色器 A 使用 texA,着色器 B 使用 texB。然后,尽管着色器 A 和着色器 B 都没有使用 texA,但两种纹理都将在两个程序中枚举(我使用的是单独的程序,所以每个着色器对应一个程序)。一个后果是我不能在一个文件中定义许多纹理,因为着色器将无法链接(它编译成功,但链接器随后抱怨纹理采样器的数量超过了硬件限制)。另一个问题是我在做自动资源绑定,而我的着色器有很多错误的资源依赖。

那么有没有办法告诉着色器编译器/链接器从单独的程序中删除所有未使用的资源?

【问题讨论】:

  • 所以澄清一下,您有一些通用代码定义了一堆采样器并包含在许多着色器程序中。即使大多数采样器没有在每个程序中使用(所以你认为它们可以被编译出来)你仍然会因为定义太多而出错?
  • @jozxyqk 没错。在 HLSL 文件中,我可以拥有任意数量的纹理或统一缓冲区。只有这些着色器实际使用的纹理(缓冲区)才会包含在着色器中。在 GLSL 中,当我在文件中定义采样器或统一缓冲区时,所有单独的着色器程序都会在程序自省中列出该资源。
  • 例如,您可以使用#idef 仅在着色器 B 中声明 texB。
  • 您使用的是 Intel HD4000 GPU 吗?很确定这是一个驱动程序错误,驱动程序不会杀死死采样器制服。

标签: c++ opengl opengl-es


【解决方案1】:

着色器采样器单元不是用来选择纹理,而是将纹理单元传递给着色器。纹理本身绑定到纹理单元。所以选择使用哪个纹理不应该在着色器中完成,而是在宿主程序中完成。

如果您的 OpenGL 实现(=GPU 驱动程序)支持这些,您也可以使用无绑定纹理。

【讨论】:

  • 我不太擅长 OpenGL 术语,这有时让我很困惑。我所做的是这个实验:我在一个文件中定义了许多纹理采样器(比如 64 个)。然后我写了一堆访问这些采样器的函数,但是文件中的任何着色器都不会调用这些函数。所以实际上在着色器中根本没有访问采样器。我能够成功编译该着色器,但随后出现此错误:OPENGL DEBUG MESSAGE: GLSL link failed for program 2, "": Number of Fragment Texture Image Units exceeds HW limits.
  • 另一个问题是,如果在文件中定义了统一缓冲区,那么即使着色器不访问缓冲区,每个程序的程序自省都会返回此缓冲区。
  • @Egor 采样器为您映射一个 TIU(硬件纹理图像单元)。您在着色器中请求了太多,而您的代码架构可能应该是您只需要其中一个,而只需在您的 GL API 调用中使用 TIU #0 即可,无论哪个纹理与哪个着色器一起使用。其他人都已经解释过了,所以我真的不知道为什么我只是用不同的词来写这篇文章。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 1970-01-01
  • 1970-01-01
  • 2015-09-27
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多