可能的渲染性能优化

时间:2015-04-09 18:52:00

标签: c# opengl performance-testing opentk

我今天正在使用C#和OpenTK做一些基准测试,只是为了看看在帧率下降之前我实际可以渲染多少。我得到的数字非常天文,我对我的测试结果非常满意。

在我的项目中,我正在加载搅拌器猴子,它是968个三角形。然后我实例化并渲染100次。这意味着我每帧渲染96,800个三角形。这个数字远远超过我在游戏中任何给定场景中需要渲染的任何数字。在此之后,我进一步推动了它,并在不同的位置渲染了2000只猴子。我现在渲染了惊人的1,936,000(每帧近200万个三角形),帧速率仍然锁定在每秒60帧!这个号码让我大吃一惊。我进一步推动它,最后帧速率开始下降,但这只意味着每帧大约有400万个三角形,并且实例化。

我只是想知道,因为我正在使用一些传统的OpenGL,如果仍然可以进一步推动 - 或者我是否应该打扰?

对于我的测试,我加载了blender monkey模型,使用不推荐的调用将其存储到显示列表中:

modelMeshID = MeshGenerator.Generate( delegate {
            GL.Begin( PrimitiveType.Triangles );
            foreach( Face f in model.Faces ) {
                foreach( ModelVertex p in f.Points ) {
                    Vector3 v = model.Vertices[ p.Vertex ];
                    Vector3 n = model.Normals[ p.Normal ];
                    Vector2 tc = model.TexCoords[ p.TexCoord ];
                    GL.Normal3( n.X , n.Y , n.Z );
                    GL.TexCoord2( tc.Y , tc.X );
                    GL.Vertex3( v.X , v.Y , v.Z );
                }
            }
            GL.End();
        } );

然后调用该列表x次。 我的问题是,如果我将VAO(顶点阵列对象)放入显示列表而不是旧的GL.Vertex3 api,我是否可以加快速度?这会影响性能吗?或者它会在显示列表中创建相同的结果吗?

这是一个几千的屏幕抓取:

enter image description here

我的系统规格:

CPU: AMD Athlon IIx4(quad core) 620 2.60 GHz
Graphics Card: AMD Radeon HD 6800

2 个答案:

答案 0 :(得分:3)

  

我的问题是,如果我将VAO(顶点阵列对象)放入显示列表而不是旧的GL.Vertex3 api,我是否可以加快速度?这会影响性能吗?或者它会在显示列表中创建相同的结果吗?

没有

您遇到的主要问题是,显示列表和顶点阵列彼此之间并不顺畅。使用缓冲对象它们可以工作,但显示列表本身就像立即模式绘图API一样遗留下来。

然而,即使您设法从显示列表中获取VBO绘图,也会略有改进:在编译显示列表时,OpenGL驱动程序知道,到达的所有内容都将是&# 34;冻"最终。这允许一些非常激进的内部优化;所有几何数据都将打包到GPU上的缓冲区对象中,状态更改将被合并。 AMD在这场比赛中并不像NVidia那么出色,但他们也不错;显示列表大量用于CAD应用程序,在ATI解决娱乐市场之前,他们专注于CAD,因此他们的显示列表实现并不坏。如果将特定绘图调用所需的所有相关状态更改打包到显示列表中,则在调用显示列表时,您可能会进入快速路径。

  

我进一步推动它,最后帧速率开始下降,但这只意味着每帧大约有400万个三角形,并且实例化。

实际上限制你的是调用显示列表的开销。我建议你在DL中添加更多的几何体,然后再试一次。

显示列表非常有效。从现代OpenGL中删除它们主要是因为它们只能用于立即模式绘制命令。最近的事情,如变换反馈和条件渲染,很难集成到显示列表中。所以他们被删除了;这是理所当然的,因为显示列表有点尴尬。

现在,如果你看看Vulkan,基本的想法是在命令缓冲区中预先设置尽可能多的绘图命令(状态更改,资源绑定等),并重用这些命令以获取不同的数据。这就像你可以创建多个显示列表并让它们成为婴儿一样。

答案 1 :(得分:2)

使用顶点列表,beginend会导致猴子几何体每次迭代都会发送到GPU,通过PCI-E,这是渲染过程中最慢的内存接口。此外,根据您的总帐实施情况,对GL的每次调用都可能会有更多或更少的开销。如果您使用缓冲区对象,那么所有开销都将消失,因为您只需将猴子发送一次,然后您需要的只是每次迭代的绘制调用。

然而,猴子的几何形状很小(只有几kb),所以通过PCI-E总线发送(以16 GB / s的速度?),再加上几何循环"几何循环&# 34;甚至不需要一毫秒。即使这样也不会触及你的帧速率,因为除非你明确地synchronizing,否则它将被流水线完全吸收:当GPU仍然忙于渲染前一帧时,复制和绘制调用将会运行。当时,GPU开始渲染下一帧,数据已经存在。

这就是为什么我猜测,鉴于你有一个相当优化的GL实现(好的驱动程序),使用缓冲区对象,不会产生任何加速。请注意,面对更大,更复杂的几何体和渲染操作,缓冲对象当然对性能至关重要。在缓冲调用之间,小缓冲区甚至可能会在芯片上缓存。

然而,作为一个严重的速度怪胎,你肯定想要仔细检查并验证这些猜测:)

相关问题