一个小的测试程序(见下文)显示了不稳定的输出,我认为这是由 OpenGL glutSwapBuffer() 期间奇怪的时序抖动引起的。与平均水平相比,测试程序经常显示单个帧的渲染时间非常长(~330 微秒与我机器上的~5.8 毫秒)程序的输出显示:
[...]
render time: 330us
render time: 372us
render time: 330us
render time: 331us
render time: 5820us
render time: 335us
render time: 332us
render time: 324us
render time: 346us
[...]
设置:快速 PC(Intel i7 CPU @3.2GHz)、Ubuntu 12.04、NVIDIA GTS450 板、最新的 GL 驱动程序:OpenGL 渲染器字符串:GeForce GTS 450/PCIe/SSE2 OpenGL 版本字符串:4.3.0 NVIDIA 310.19 Samsung Display (23" @我假设是 60Hz,因为所有这些都有 60Hz)
在上面的测试用例中,我通过以下方式明确否决了 vblank 同步:__GL_SYNC_TO_VBLANK=0
启用 vblank 后,我的时间也很不稳定:
__GL_SYNC_TO_VBLANK=1
[...]
render time: 9169us
render time: 14548us
render time: 14613us
render time: 16057us
render time: 18075us
[...]
我还使用了其他参数,例如将 X 服务器置于高优先级(sudo schedtool -p 0 -n -20 -N pgrep X
)或将程序本身置于高优先级(chrt -p -a --fifo 99 ... )
仍然生涩的动画仍然存在 - 这(这是我的假设)是由奇怪的时间引起的。
没有 `glutSwapBuffers();' 的计时 在代码中显示了非常稳定的输出:
[...]
render time: 2us
render time: 2us
render time: 2us
render time: 1us
render time: 2us
[...]
因此可以排除外部(其他过程)影响。
谁能解释这种行为?
知道如何改进吗?
该程序:
#include <stdio.h>
#include <GL/gl.h>
#include <GL/glut.h>
#include <time.h>
GLfloat gfPosX = 0.0;
GLfloat gfDeltaX = .01;
#define TS_TOUSEC(x) (x.tv_sec * 1000000L + (x.tv_nsec / 1000))
struct timespec t1, t2;
void Draw() {
int x = 0;
glClear(GL_COLOR_BUFFER_BIT);
glColor3f(1.0, 1.0, 1.0);
clock_gettime(CLOCK_REALTIME, &t1);
glBegin(GL_LINES);
glVertex3f(gfPosX, 0.25, 0.0);
glVertex3f(gfPosX, 0.75,0.0);
glEnd();
clock_gettime(CLOCK_REALTIME, &t2);
glutSwapBuffers();
printf("render time: %5uus\n", TS_TOUSEC(t2) - TS_TOUSEC(t1));
gfPosX += gfDeltaX;
if (gfPosX >= 1.0 || gfPosX <= 0.0) {
gfDeltaX = -gfDeltaX;
}
}
void Timer(int iUnused)
{
glutPostRedisplay();
glutTimerFunc(5, Timer, 0);
}
void Initialize() {
glClearColor(0.0, 0.0, 0.0, 0.0);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}
int main(int iArgc, char** cppArgv) {
glutInit(&iArgc, cppArgv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(250, 250);
glutInitWindowPosition(200, 200);
glutCreateWindow("XoaX.net");
Initialize();
glutDisplayFunc(Draw);
Timer(0);
glutMainLoop();
return 0;
}