Nvidia GPU上的统一缓冲区大小

问题描述 投票:0回答:1

我使用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上的这个值如此之低?有没有其他方法可以将大数组传递给我的着色器?

c# opengl nvidia
1个回答
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可能是您方案中最自然的选择。

© www.soinside.com 2019 - 2024. All rights reserved.