0

我正在使用 opengl 3.3,使用完全流式传输的 VBO 渲染一个自上而下的基于图块的世界。

在遇到一些滞后后,我做了一些基准测试,结果发现很可怕!

在此处输入图像描述

让我解释一下图片。第一个标记的方块是我使用最简单的着色器运行我的游戏。没有闪电,什么都没有!我只是上传 5000 个顶点并绘制它们。我的内存负载约为 20-30%,cpu-load 30-40%

第二个是闪电。每个灯光都作为数组上传到片段着色器,每个片段都会处理灯光。负载约 40-50%。100% 有 60 盏灯。

第三个是延迟着色。首先,我将法线和漫反射绘制到 FBO,然后将每个灯光渲染到默认 FB,同时读取这些灯光。负载约为 80%。基本上不受灯光数量的影响。

这些是我渲染的场景:

在此处输入图像描述

在此处输入图像描述

如您所见,没有什么花哨的。是复古风格。我的计划是增加大量的复杂性,并且仍然在低端计算机上运行流畅。我的是i7 nvidia 660M,所以应该没有问题。

作为比较,我运行了魔兽争霸 3,它占用了大约 50-60% 的负载,20% 的内存。

我注意到的一件奇怪的事情是,如果我禁用垂直同步并且不在交换缓冲区之前调用 glFinish,负载会显着下降。然而,时钟上升并产生热量(53C*)。

现在,首先我想知道你是否认为这是正常的。如果不是,那么我的瓶颈可能是什么?会不会是我的流媒体 VBO?我试过双重缓冲和孤立,但没有。将 sprite 的数量加倍基本上会增加 5-10% 的内存负载。GPU负载基本保持不变。

我知道这个问题不容易回答,但我会根据您的需要提供更多详细信息。不想在这里发布我的 20000 行代码。

哦,还有一件事......它会波动。绘制调用是相同的,但负载可以从 2-100% 变化,只要感觉。

更新:

我的主循环如下所示:

交换缓冲区

renderAndDoGlCalls

更新GameAndPoll

如果还有时间就睡觉(1/60 秒)

重复。

如果没有 v-sync、glflush 或 glfinsih,这会导致使用百分比:

交换:0.16934400677376027

任:0.9929640397185616

upp:0.007698000307920012

民意调查:0.0615780024631201

睡眠:100.39487801579511

在交换缓冲区之前使用 glFinish:

交换:26.609977064399082(这通常会上升到 80%)

任:1.231584049263362

upp:0.010266000410640016

民意调查:0.07697400307896013

睡眠:74.01582296063292

使用 Vsync 启动良好,通常与使用 glFinish 相同,然后是 bam!:

交换:197.84934791397393

任:1.221324048852962

upp:0.007698000307920012

民意调查:0.05644800225792009

睡眠:0.002562000102480004

它保持这种状态。

4

1 回答 1

1

让我澄清一下……如果我在所有 opengl 调用之后立即调用 swapbuffers,我的 CPU 会停滞 70% 的更新时间,让我什么也不做。这样,在我再次调用交换之前,我会给 GPU 尽可能长的时间来完成后缓冲。

您实际上无意中导致了相反的情况。

SwapBuffers 导致调用线程停止的唯一时间是当预渲染帧队列已满并且它必须等待 VSYNC 刷新完成的帧时。在任何给定时刻,CPU 很容易比 GPU 领先 2-3 帧,并且不是当前帧完成导致等待(在这种情况下已经有一个完成的帧需要交换)。

发生等待是因为驱动程序无法从后到前交换后备缓冲区,直到 VBLANK 信号滚动(每 16.667 毫秒才发生一次)。驱动程序实际上会在等待向上交换时继续接受命令,直到达到队列交换的某个限制(NVIDIA 硬件上的预渲染帧/AMD 上的翻转队列大小)。一旦达到该限制,GL 命令将导致阻塞,直到后台缓冲区被交换。

您在帧结束时正在睡觉,因此没有明显的 CPU/GPU 并行性发展;实际上,您更有可能以这种方式跳过一帧。

这就是你在这里看到的。绝对最坏的情况是当您睡 1 毫秒时太晚而无法及时为 VBLANK 交换缓冲区。然后两帧之间的时间变为 16.66667 + 15.66667 = 32.33332 毫秒。如果您不添加自己的等待时间,这将导致不会发生的口吃。驱动程序可以轻松地从后到前复制后台缓冲区,并在您添加的那 1 个额外毫秒内继续接受命令,但它会在下一帧开始时额外阻塞 15 个毫秒。

为避免这种情况,您希望在发出帧的所有命令后尽快交换缓冲区。通过这种方式,您最有可能满足 VBLANK 的最后期限。由于睡眠时间减少,报告的 CPU 使用率可能会上升,但性能应该使用帧时间而不是计划的 CPU 时间来衡量。

如问题中所述,VSYNC 和讨论的预渲染帧限制将使您的 CPU 和 GPU 不会失控并产生大量热量。

于 2015-08-30T16:11:41.767 回答