Nvidia GPU上的统一缓冲区大小

时间:2017-12-21 20:57:22

标签: c# opengl nvidia

我使用C#和OpenTK来访问OpenGL API。我的项目使用细分来渲染高度图。我的曲面细分控制着色器将一个正方形分成64个正方形的网格,我的曲面细分评估着色器为这些点添加了垂直偏移。垂直偏移存储在统一的浮动缓冲区中,如下所示:

uniform float HeightmapBuffer[65 * 65];

当我使用AMD Radeon 8250 GPU在笔记本电脑上运行项目时,一切正常。当我尝试在Nvidia显卡上运行时,问题就出现了。我尝试过较旧的GT 430和全新的GTX 1060,但效果相同:

Tessellation evaluation info
----------------------------
0(13) : error C5041: cannot locate suitable resource to bind variable "HeightmapBuffer". Possibly large array.

当我研究这个问题时,我发现GL_MAX_UNIFORM_BLOCK_SIZE变量在AMD上返回~500MB,在两个Nvidia芯片上返回65.54 kB。这有点奇怪,因为我的阵列实际上只使用了16.9 kB,所以我甚至不确定" BLOCK SIZE"实际上限制了一个变量的大小。也许它限制了传递给一个着色器的所有制服的大小?即便如此,我也无法相信我的程序会使用65 kB。

请注意,我也试过去常见的'通过使用纹理的方式,但我认为插值有问题,所以当将两个相邻的高度图放在一起时,边框不匹配。在另一侧有一个统一的缓冲阵列,事情很完美。

那么GL_MAX_UNIFORM_BLOCK_SIZE的实际含义是什么?为什么Nvidia GPU上的这个值如此之低?有没有其他方法可以将大数组传递给我的着色器?

1 个答案:

答案 0 :(得分:3)

  

当我研究这个问题时,我发现GL_MAX_UNIFORM_BLOCK_SIZE变量在AMD上返回~500MB,在Nvidia芯片上返回65.54 kB。

GL_MAX_UNIFORM_BLOCK_SIZE是错误的限制。这仅适用于Uniform Buffer Objects

您只需声明一个数组

uniform float HeightmapBuffer[65 * 65];

在统一区块之外。由于您似乎在tesselation评估着色器中使用它,因此相关限制为MAX_TESS_EVALUATION_UNIFORM_COMPONENTS(每个可编程阶段都有一个单独的限制)。此组件限制只计算浮动组件的数量,因此vec4将消耗4个组件,float只有一个组件。

在您的特定情况下,最新的GL规范,[GL 4.6核心配置文件](https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf) 在撰写本文时,只保证最小值为1024(= 4kiB),并且方式超出该限制。

对于这样的数据量使用普通制服实际上是一个非常糟糕的主意。您应该考虑使用UBOsTexture Buffer ObjectsShader Storage Buffer Objects甚至纯纹理来存储数组。在您的方案中,UBO可能是最自然的选择。