我正在使用AMD Radeon HD 6630M的MacMini '11。我正在使用数组结构绘制一个网格,一切都很好:60 fps(使用CVDisplayLink)。我使用具有内置属性的着色器。生活很好。我正在转向使用一组结构(交错),因为我知道这是“现代”GPU的首选。属性在着色器中定义。网格绘制精美。但是当我这样做时,帧速率下降了大约33%(到40 fps)。这些电话有多个副本。使用Instruments:Time Profiler,我得到以下比较:
Using structure of arrays (60 fps)
Running Time Self Symbol Name
3.0ms 0.0% 3.0 0x21b76c4 ATIRadeonX3000GLDriver
2.0ms 0.0% 0.0 gldUpdateDispatch ATIRadeonX3000GLDriver
2.0ms 0.0% 0.0 gleDoDrawDispatchCore GLEngine
2.0ms 0.0% 0.0 glDrawElements_ACC_Exec GLEngine
2.0ms 0.0% 0.0 glDrawElements libGL.dylib
2.0ms 0.0% 0.0 -[Mesh draw] me
Using array of structures (40 fps)
Running Time Self Symbol Name
393.0ms 7.4% 393.0 0x86f6695 ?
393.0ms 7.4% 0.0 gleDrawArraysOrElements_ExecCore GLEngine
393.0ms 7.4% 0.0 glDrawElements_IMM_Exec GLEngine
393.0ms 7.4% 0.0 glDrawElements libGL.dylib
393.0ms 7.4% 0.0 -[Mesh draw] me
看起来libGL正在决定向不同的方向发展,结构数组似乎没有被调用X3000驱动程序。它是在Apple软件模拟器中执行的吗?我应该继续使用数组结构吗?有没有人见过这样的东西?
属性代码来自Apple示例,在我的应用程序中使用(至少10个其他区域),在这些区域没有性能影响。这是来自慢速版本。正如我所提到的,我在快速版本中使用内置属性,因为数据不是交错的。渲染点亮,只是很慢。
我希望这就是你要找的东西:
// Step 5 - Bind each of the vertex shader's attributes to the programs
[self.meshShader addAttribute:@"inPosition"];
[self.meshShader addAttribute:@"inNormal"];
[self.meshShader addAttribute:@"inTexCoord"];
// Step 6 - Link the program
if([[self meshShader] linkShader] == 0){
self.posAttribute = [meshShader attributeIndex:@"inPosition"];
self.normAttribute = [meshShader attributeIndex:@"inNormal"];
self.texCoordAttribute = [meshShader attributeIndex:@"inTexCoord"];
...
- (void) addAttribute:(NSString *)attributeName
{
if ([attributes containsObject:attributeName] == NO){
[attributes addObject:attributeName];
glBindAttribLocation(program, [attributes indexOfObject:attributeName],
[attributeName UTF8String]);
}
}
更新 经过进一步调查: 1)我正在使用dhpoWare的modelObj加载器(已修改),因为它使用了交错的结构数组,它的性能就像我的结构数组一样 - 只是没有点击。我可能会错误地解释乐器。 modelObj代码确实调用glDrawElements_IMM_Exec,它也以环形方式调用gleDoDrawDispatchCore。我不确定它是否只是在glDrawElements_IMM_Exec上累积一堆调用,然后通过gleDoDrawDispatchCore将它们爆破。不知道。 2)我认为Instruments有问题,因为它显示GLEngine调用我未使用的内部3ds对象方法之一,它没有外部钩子。我通过在那里设置Xcode断点进行了双重检查,它从未跳过。我不再做3DS了。
我想我会继续环顾四周,也许会偶然发现答案。如果有人愿意就一系列结构是否可行而给我一个意见,我们将不胜感激。
解: 我在前端添加了一个VBO,一切都很顺利。原始代码来自OpenGL ES 2.0指南,添加VBO修复了我的问题。帧速率为60,1 ms驱动程序调用。这是代码:
glGenVertexArrays(1, &vaoName);
glBindVertexArray(vaoName);
// new - create VBO
glGenBuffers(1, &vboName);
glBindBuffer(GL_ARRAY_BUFFER, vboName);
// Allocate and load position data into the VBO
glBufferData(GL_ARRAY_BUFFER, sizeof(struct vertexAttribs) * self.numVertices,
vertexAttribData, GL_STATIC_DRAW);
// end of new
NSUInteger vtxStride = sizeof(struct vertexAttribs);
//GLfloat *vtxBuf = (GLfloat *)vertexAttribData; // no longer use this
GLfloat *vtxBuf = (GLfloat *)NULL; // use this instead
glEnableVertexAttribArray(self.posAttribute);
glVertexAttribPointer(self.posAttribute, VERTEX_POS_SIZE, GL_FLOAT, GL_FALSE,
vtxStride, vtxBuf);
vtxBuf += VERTEX_POS_SIZE;
glEnableVertexAttribArray(self.normAttribute);
glVertexAttribPointer(self.normAttribute, VERTEX_NORM_SIZE, GL_FLOAT, GL_FALSE,
vtxStride, vtxBuf);
vtxBuf += VERTEX_NORM_SIZE;
glEnableVertexAttribArray(self.texCoordAttribute);
glVertexAttribPointer(self.texCoordAttribute, VERTEX_TEX_SIZE, GL_FLOAT, GL_FALSE,
vtxStride, vtxBuf);
...
答案 0 :(得分:0)
用于在内存中实现单位步幅访问的数组结构是经验法则。它不仅适用于GPU,也适用于CPUS和Intel Xeon Phi等协处理器。
在您的情况下,我不相信这部分代码会被发送到GPU,而是性能损失是由于非单位步进内存访问(CPU到/来自内存)。