有没有一种高效的方法可以超过GL_MAX_VIEWPORTS?

4
我正在实现Oikonomidis et al., 2011中提出的姿态估计算法,其中涉及在N个不同的假设姿势下渲染网格(N可能约为64)。第2.5节建议使用实例化加速计算,同时生成多个渲染(之后将每个渲染缩减为GPU上的单个数字),从他们的描述中可以得知,他们找到了一种同时生成N个渲染的方法。
在我的实现设置阶段,我使用OpenGL视口数组来定义GL_MAX_VIEWPORTS视口。然后在渲染阶段,我将一个GL_MAX_VIEWPORTS模型-姿势矩阵数组传输到GPU内存中的mat4uniform数组中(我只关心位置和方向),并在我的几何着色器中使用gl_InvocationID来选择网格的每个多边形所需的适当姿势矩阵和视口。

GL_MAX_VIEWPORTS在我的机器上是16(我有一台GeForce GTX Titan),所以这种方法将允许我一次在GPU上渲染多达16个假设。这可能足够快,但我仍然对以下内容感到好奇:

是否存在一个解决GL_MAX_VIEWPORTS限制的方法,比调用我的渲染函数ceil(double(N)/GL_MX_VIEWPORTS)次更快?

我只是几周前开始学习基于着色器的OpenGL方法,所以我还不知道所有的技巧。最初,我想用内置视口支持的组合来替换它:

  1. 一个几何着色器,在透视投影后将h*gl_InvocationID添加到顶点的y坐标,并将gl_InvocationID传递到片段着色器;和
  2. 一个片段着色器,使用y坐标来丢弃符合y<gl_InvocationID*h || y>=(gl_InvocationID+1)*h条件的片段。
但是,我因为担心分支和discard会对性能产生很大的影响而放弃了进一步研究这个想法。
上述论文的作者发布了一个技术报告,描述了他们的一些GPU加速方法,但它并不详细,无法回答我的问题。第3.2.3节说:“在几何实例化期间,视口信息被附加到每个顶点...自定义像素着色器剪裁在其预定义视口之外的像素”。这听起来与我上面描述的解决方法类似,但他们使用的是Direct3D,所以很难比较他们在2011年使用Direct3D能够实现的成果与我今天在OpenGL中能够实现的成果。
我意识到,对我的问题唯一明确的答案是实施这个解决方法并测量其性能,但目前这只是一个低优先级的好奇心,我没有在其他地方找到答案,所以我希望更有经验的GLSL用户能够提供节省时间的智慧。

你的视口(即glViewport的参数)从一个"视口"到另一个"视口"是否真正发生了变化?根据你算法的简要描述,我认为它们并没有发生变化。 - Nicol Bolas
1个回答

8

从文章的简略浏览来看,我认为实际视口没有改变。也就是说,您仍然以相同的宽度/高度和X/Y位置进行渲染,并具有相同的深度范围。

您想要改变的是要呈现的图像。这就是gl_Layer的作用;更改要呈现到帧缓冲器所附加的图像数组中的哪个层。

因此,只需将所有顶点的gl_ViewportIndex设置为0即可。或者更具体地说,根本不需要设置。

GS实例调用的数量不一定是限制;这是您的选择。 GS调用可以写入多个基元,每个基元写入不同的层。因此,您可以让每个实例分别写入4个基元,每个基元分别写入4个单独的层。

您唯一的限制应该是您可以使用的层数(由 GL_MAX_ARRAY_TEXTURE_LAYERSGL_MAX_FRAMEBUFFER_LAYERS 管理,两者都必须至少为 2048),以及单个 GS 调用可以发出的基元和顶点数据的数量(这有点复杂)。


1
谢谢您的建议!花了一些时间才弄清楚如何渲染到纹理数组的深度附件,然后读取结果以验证其是否有效(我不得不从使用glReadPixels切换到glGetTextureImage)。不幸的是,限制远远不及GL_MAX_ARRAY_TEXTURE_LAYERS高,因为您只能创建MAX_GEOMETRY_SHADER_INVOCATIONS几何着色器实例,在我的机器上为32。虽然这仍然比GL_MAX_VIEWPORTS限制好,所以我接受了您的答案。 - Ose
我在我的回答中提到的技术报告的第3.2.3节被称为“多视口剪裁”,因此似乎很清楚他们并行地渲染到不同的视口中。他们是使用内置的视口支持还是通过“discard”模拟它,以及他们是否真的能够同时渲染所有假设,这些问题都不清楚。 - Ose
1
@Ose:GS调用不是限制;请看我的回答。 - Nicol Bolas
哦,好主意,我会写多个基元!再次感谢你的帮助! - Ose
1
我遇到了另一个限制:可用uniform的数量 (https://www.khronos.org/opengl/wiki/Uniform_(GLSL)#Implementation_limits)。我需要一个包含`N`个`mat4`(每个假设一个)的数组,并额外加一个用于投影矩阵的`mat4`,但我的电脑不允许我定义超过128个`mat4` uniform。这个问题建议使用统一缓冲对象来解决:https://dev59.com/tnrZa4cB1Zd3GeqP1mDa 。但是我可能也用不到超过127个假设。 - Ose

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接