4

许多文章通过指定固定绑定点来描述使用原子计数器:

//Shader:
layout(binding = 0, offset = 0) uniform atomic_uint myAtomicCounter;

//App code
glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, myBufferHandle);

在这里,硬编码绑定点binding = 0在着色器和应用程序代码中都指定。我猜这些文章是这样做的,因为,

原子计数器没有分配位置,并且不能使用Uniform*命令进行修改。属于程序对象的原子计数器的绑定、偏移量和步幅在每次成功重新链接后都将失效并分配新的。[shader_atomic_counters]

在您想要一些更模块化的着色器代码之前,上述内容很好。例如,我有两个着色器包含文件,每个都需要一个原子计数器,我将其编写为不知道另一个的可插入代码。显然我不想指定硬编码绑定点,我希望应用程序自动处理它。我真的不在乎他们使用哪个绑定点,只是他们不一样。

顶点着色器属性看起来相似。我可以在着色器链接之前在运行时()强制绑定位置,glBindAttribLocation或者让 OpenGL 为我选择它们,然后查询结果(glGetAttribLocation)。我还可以搜索所有属性 ( glGetActiveAttrib)。

如何为原子计数器实现自动唯一绑定点,这样它们就不会被硬编码,我可以混合着色器代码?

我可以看到几种可能的方法,但仍然存在链接后不更改它们的限制:

  1. 不要在着色器中指定绑定点,让 OpenGL 在链接时选择一个。我不知道OpenGL是否会这样做。如果是这样,您如何查询以找到使用的绑定点?
  2. 在链接之前查询着色器对象以查找原子计数器。然后给他们唯一的绑定位置,就像glBindAttribLocation属性一样。是否有分配绑定点的机制?
  3. 解析所有着色器代码,寻找原子计数器并用着色器代码本身中的唯一索引替换绑定点,可能使用#define宏。最后的手段。我真的不想这样做。
4

2 回答 2

1

第 1 点:binding原子计数器的布局参数不是可选的。

关于第 2 点:因为binding不是可选的,所以能够从 OpenGL 代码中设置它是没有意义的。

所以你唯一的办法是#3。

于 2015-12-14T05:50:21.150 回答
1

您可以使用 查询原子计数器glGetActiveUniform。然后获取缓冲区索引,最后是绑定点:

int atomicCounterIndex;
glGetActiveUniformsiv(programId, count, index, 
        GL_UNIFORM_ATOMIC_COUNTER_BUFFER_INDEX, &atomicCounterIndex);
glGetActiveAtomicCounterBufferiv(programId, atomicCounterIndex, 
        GL_ATOMIC_COUNTER_BUFFER_BINDING, &myBufferHandle)

如文档中所述,这从 OpenGL 4.2 开始有效

于 2017-04-30T20:47:07.973 回答