哪个是编写此 gl 代码的正确方法
which one is proper method of writing this gl code
我一直在用 opengl 和处理纹理做一些实验。
在我的实验中,我有一个随机生成的 (int) 二维数组
int mapskeleton[300][300];
然后我有自己的 obj 文件加载器来加载带有纹理的 obj
m2d wall,floor;//i initialize and load those files at start
用于记录我使用的渲染时间统计
bool Once = 1;
int secs = 0;
现在到这里的渲染代码我做了我的实验
// Code A: Benchmarked on radeon 8670D
// Takes 232(average) millisecs for drawing 300*300 tiles
if(Once)
secs = glutGet(GLUT_ELAPSED_TIME);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_Wall){
glBindTexture(GL_TEXTURE_2D,wall.texture);
glPushMatrix();
glTranslatef(j*10,i*10,0);
wall.Draw();//Draws 10 textured triangles
glPopMatrix();
}
if(mapskeleton[j][i] == skel_floor){
glBindTexture(GL_TEXTURE_2D,floor.texture);
glPushMatrix();
glTranslatef(j*10,i*10,0);
floor.Draw();//Draws 2 textured triangles
glPopMatrix();
}
}
}
if(Once){
secs = glutGet(GLUT_ELAPSED_TIME)-secs;
printf("time taken for rendering %i msecs",secs)
Once = 0;
}
其他代码为
// Code B: Benchmarked on radeon 8670D
// Takes 206(average) millisecs for drawing 300*300 tiles
if(Once)
secs = glutGet(GLUT_ELAPSED_TIME);
glBindTexture(GL_TEXTURE_2D,floor.texture);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_floor){
glPushMatrix();
glTranslatef(j*10,i*10,0);
floor.Draw();
glPopMatrix();
}
}
}
glBindTexture(GL_TEXTURE_2D,wall.texture);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_Wall){
glPushMatrix();
glTranslatef(j*10,i*10,0);
wall.Draw();
glPopMatrix();
}
}
}
if(Once){
secs = glutGet(GLUT_ELAPSED_TIME)-secs;
printf("time taken for rendering %i msecs",secs)
Once = 0;
}
对我来说,代码 A 看起来不错,一个人(初学者)查看代码。但基准说不同。
我的 gpu 似乎喜欢代码 B。我不明白为什么代码 B 的渲染时间更短?
OpenGL 状态的更改通常代价高昂 - 驱动程序的 and/or GPU 数据结构和缓存可能会失效。在您的情况下,所讨论的变化是绑定不同的纹理。在代码 B 中,您执行了两次。在代码 A 中,您可以轻松地执行数千次。
编写 OpenGL 渲染程序时,您通常需要为设置 A 设置管道,渲染需要设置 A 的所有内容,为设置 B 重新设置管道,渲染需要设置 B 的所有内容,等等.
@Angew 介绍了为什么一个选项比另一个更有效。但是有一个重要的点需要非常清楚地说明。根据您问题的内容,尤其是此处:
for recording statistics of render times
my gpu seems to like code B
您似乎试图衡量 rendering/GPU 表现。
您根本没有在衡量 GPU 性能!
您测量设置状态和进行绘制调用的时间。 OpenGL 允许 GPU 与 CPU 上执行的代码异步操作。当您进行(大多数)OpenGL 调用时,您应该牢记的画面是您正在 提交工作 给 GPU 以供稍后执行。不知道 GPU 何时完成这项工作。它绝对不会在调用 returns.
时发生(除了极少数你想在速度关键代码中避免的调用)
您在代码中测量的纯粹是进行这些调用的 CPU 开销 。这包括您自己的代码中发生的事情,以及驱动程序代码中发生的事情,用于处理调用和准备稍后提交给 GPU 的工作。
我并不是说测量没有用。最小化 CPU 开销非常重要。你只需要非常清楚你实际测量的是什么,并确保你得出正确的结论。
我一直在用 opengl 和处理纹理做一些实验。 在我的实验中,我有一个随机生成的 (int) 二维数组
int mapskeleton[300][300];
然后我有自己的 obj 文件加载器来加载带有纹理的 obj
m2d wall,floor;//i initialize and load those files at start
用于记录我使用的渲染时间统计
bool Once = 1;
int secs = 0;
现在到这里的渲染代码我做了我的实验
// Code A: Benchmarked on radeon 8670D
// Takes 232(average) millisecs for drawing 300*300 tiles
if(Once)
secs = glutGet(GLUT_ELAPSED_TIME);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_Wall){
glBindTexture(GL_TEXTURE_2D,wall.texture);
glPushMatrix();
glTranslatef(j*10,i*10,0);
wall.Draw();//Draws 10 textured triangles
glPopMatrix();
}
if(mapskeleton[j][i] == skel_floor){
glBindTexture(GL_TEXTURE_2D,floor.texture);
glPushMatrix();
glTranslatef(j*10,i*10,0);
floor.Draw();//Draws 2 textured triangles
glPopMatrix();
}
}
}
if(Once){
secs = glutGet(GLUT_ELAPSED_TIME)-secs;
printf("time taken for rendering %i msecs",secs)
Once = 0;
}
其他代码为
// Code B: Benchmarked on radeon 8670D
// Takes 206(average) millisecs for drawing 300*300 tiles
if(Once)
secs = glutGet(GLUT_ELAPSED_TIME);
glBindTexture(GL_TEXTURE_2D,floor.texture);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_floor){
glPushMatrix();
glTranslatef(j*10,i*10,0);
floor.Draw();
glPopMatrix();
}
}
}
glBindTexture(GL_TEXTURE_2D,wall.texture);
for(int i=0;i<mapHeight;i++){
for(int j=0;j<mapWidth;j++){
if(mapskeleton[j][i] == skel_Wall){
glPushMatrix();
glTranslatef(j*10,i*10,0);
wall.Draw();
glPopMatrix();
}
}
}
if(Once){
secs = glutGet(GLUT_ELAPSED_TIME)-secs;
printf("time taken for rendering %i msecs",secs)
Once = 0;
}
对我来说,代码 A 看起来不错,一个人(初学者)查看代码。但基准说不同。 我的 gpu 似乎喜欢代码 B。我不明白为什么代码 B 的渲染时间更短?
OpenGL 状态的更改通常代价高昂 - 驱动程序的 and/or GPU 数据结构和缓存可能会失效。在您的情况下,所讨论的变化是绑定不同的纹理。在代码 B 中,您执行了两次。在代码 A 中,您可以轻松地执行数千次。
编写 OpenGL 渲染程序时,您通常需要为设置 A 设置管道,渲染需要设置 A 的所有内容,为设置 B 重新设置管道,渲染需要设置 B 的所有内容,等等.
@Angew 介绍了为什么一个选项比另一个更有效。但是有一个重要的点需要非常清楚地说明。根据您问题的内容,尤其是此处:
for recording statistics of render times
my gpu seems to like code B
您似乎试图衡量 rendering/GPU 表现。
您根本没有在衡量 GPU 性能!
您测量设置状态和进行绘制调用的时间。 OpenGL 允许 GPU 与 CPU 上执行的代码异步操作。当您进行(大多数)OpenGL 调用时,您应该牢记的画面是您正在 提交工作 给 GPU 以供稍后执行。不知道 GPU 何时完成这项工作。它绝对不会在调用 returns.
时发生(除了极少数你想在速度关键代码中避免的调用)您在代码中测量的纯粹是进行这些调用的 CPU 开销 。这包括您自己的代码中发生的事情,以及驱动程序代码中发生的事情,用于处理调用和准备稍后提交给 GPU 的工作。
我并不是说测量没有用。最小化 CPU 开销非常重要。你只需要非常清楚你实际测量的是什么,并确保你得出正确的结论。