我正在构建一个着色器程序和 GL 主机环境,它可以完成一项相对简单的任务:
- 在多个三角形(补丁)上运行 VS -> TCS -> TES -> GS 着色器阶段集。TES/TCS 确实会产生额外的镶嵌三角形。
- 创建一个由足够多的 vec4 元素组成的简单 SSBO。SSBO 将保存镶嵌的结果,即镶嵌顶点的坐标
- 在 GS 运行期间,GS 会将三角形顶点写入 SSBO,以使单个三角形的顶点步长为三个,即
(triangle1, vert1)
,(triangle1, vert2)
,(triangle1, vert3)
,(triangle2, vert1)
,(triangle2, vert2)
,(triangle2, vert3)
等。
为了索引我的 SSBO,我需要以某种方式推断“triangleID”。我仔细阅读了 GS/Tess 规格并做了一些实验。似乎 GS 内置输入只是没有它。gl_PrimitiveIDIn 似乎指的是在顶点着色器中看到的三角形的原始索引,并且在细分期间它没有增加。
最后,我想到了拥有另一个 SSBO 的想法/解决方法,该 SSBO 将具有一个“原始计数器”,atomicAdd(primCount, 1)
每次执行 GS 时都会递增:
layout ( triangles ) in;
layout ( triangle_strip, max_vertices = 3 ) out;
layout(std140, binding = 1) buffer AuxSSBO {
int primCount;
int lock;
int pad2;
int pad3;
};
layout(std140, binding = 2) writeonly buffer TrianglesSSBO {
writeonly vec4 pos[];
};
void main() {
int idx = atomicAdd(primCount, 1);
for (int i = 0; i < 3; ++i) {
gl_Position = gl_in[i].gl_Position;
gl_PrimitiveID = gl_PrimitiveIDIn;
pos[3 * idx + i] = vec4(gl_Position.xyz, 1.0);
EmitVertex();
}
EndPrimitive();
}
昨天我花了很多时间来完善上面的代码,因为我在路上遇到了各种各样的赛车条件。现在看来,它在我的 GPU/驱动程序上起到了作用,但我不完全确定它是 100% 正确的。
所以我的第一个问题是:
- 在我的情况下推断三角形索引的最佳方法是什么?上面的代码是免费的?
我的第二个问题是关于性能:
- 我有另一个基于变换反馈对象和缓冲区的任务实现,我必须说它的工作速度快 4 倍(每帧 2.0 毫秒对 0.5 毫秒)。我想知道为什么 SSBO 后端比 TF 后端慢得多,我能做些什么来让它运行得更快吗?
PS 完整代码在这里:https ://pastebin.com/SagKZEyi
PSS 使用 DrawArraysIndirect() 更新的代码在这里:https ://gist.github.com/lhog/432af74ba41259e062f18910b5904684
谢谢!