gpt4 book ai didi

ios - 使用 VBO 的 OpenGL ES iOS 绘图性能比不使用 VBO 慢很多

转载 作者:可可西里 更新时间:2023-11-01 05:09:34 26 4
gpt4 key购买 nike

我最近将当前项目中的绘图从内存阵列的标准绘图更改为 VBO。令我惊讶的是,帧速率从 60fps 显着下降到 30fps,绘制了 1200verts 的模型 8 次。进一步的分析表明,与从内存中绘制相比,使用 VBO 时 glDrawElements 花费的时间是其 10 倍。

我真的很困惑为什么会这样。有谁知道性能下降的原因是什么?

我正在运行 iOS 6.1.2 的 iPhone 5 上进行测试。

我已将我的 VBO 处理隔离到一个函数中,在该函数的顶部静态创建顶点/索引缓冲区一次。我可以使用 #ifdef USE_VBO 在普通渲染和 VBO 渲染之间切换

- (void)drawDuck:(Toy*)toy reflection:(BOOL)reflection
{
ModelOBJ* model = _duck[0].model;
int stride = sizeof(ModelOBJ::Vertex);

#define USE_VBO
#ifdef USE_VBO
static bool vboInitialized = false;
static unsigned int vbo, ibo;
if (!vboInitialized) {
vboInitialized = true;

// Generate VBO
glGenBuffers(1, &vbo);
int numVertices = model->getNumberOfVertices();
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, stride*numVertices, model->getVertexBuffer(), GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

// Generate index buffer
glGenBuffers(1, &ibo);
int numIndices = model->getNumberOfIndices();
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(unsigned short)*numIndices, model->getIndexBuffer(), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
#endif

[self setupDuck:toy reflection:reflection];


#ifdef USE_VBO
// Draw with VBO
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);

glEnableVertexAttribArray(GC_SHADER_ATTRIB_POSITION);
glEnableVertexAttribArray(GC_SHADER_ATTRIB_NORMAL);
glEnableVertexAttribArray(GC_SHADER_ATTRIB_TEX_COORD);

glVertexAttribPointer(GC_SHADER_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(ModelOBJ::Vertex, position));
glVertexAttribPointer(GC_SHADER_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(ModelOBJ::Vertex, texCoord));
glVertexAttribPointer(GC_SHADER_ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, stride, (void*)offsetof(ModelOBJ::Vertex, normal));
glDrawElements(GL_TRIANGLES, model->getNumberOfIndices(), GL_UNSIGNED_SHORT, 0);

glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
#else
// Draw with array
glEnableVertexAttribArray(GC_SHADER_ATTRIB_POSITION);
glEnableVertexAttribArray(GC_SHADER_ATTRIB_NORMAL);
glEnableVertexAttribArray(GC_SHADER_ATTRIB_TEX_COORD);

glVertexAttribPointer(GC_SHADER_ATTRIB_POSITION, 3, GL_FLOAT, GL_FALSE, stride, model->getVertexBuffer()->position);
glVertexAttribPointer(GC_SHADER_ATTRIB_TEX_COORD, 2, GL_FLOAT, GL_FALSE, stride, model->getVertexBuffer()->texCoord);
glVertexAttribPointer(GC_SHADER_ATTRIB_NORMAL, 3, GL_FLOAT, GL_FALSE, stride, model->getVertexBuffer()->normal);
glDrawElements(GL_TRIANGLES, model->getNumberOfIndices(), GL_UNSIGNED_SHORT, model->getIndexBuffer());
#endif
}

ModelOBJ::Vertex 只是 3,2,3 float for pos, texcoord, normal。索引很短。

更新:我现在已经将绘制设置(即属性绑定(bind)调用)包装到一个 VAO 中,现在性能还可以,甚至比从主内存中绘制略好一些。所以我的结论是,没有 VAO 的 VBO 支持在 iOS 上被破坏了。这个假设是否正确?

最佳答案

驱动程序很可能正在退回到软件顶点提交(CPU 从 VBO 复制到命令缓冲区)。这可能比在客户端内存中使用顶点数组更糟糕,因为我们通常缓存客户端内存,而 VBO 内容通常在 iOS 上写入组合内存中。

在 Instruments 中使用 CPU 采样器时,您会在 gleRunVertexSubmitARM 中的 glDrawArrays/glDrawElements 下看到大量时间。

退回到 SW CPU 提交的最常见原因是未对齐的属性(当前的 iOS 设备要求每个属性都是 4 字节对齐的),但您显示的 3 个属性似乎并非如此.之后,下一个最常见的原因是在单个顶点数组配置中混合客户端数组和缓冲区对象。

在这种情况下,您可能有一个杂散的顶点属性绑定(bind):一些其他数组元素可能仍处于启用状态并指向客户端数组,导致所有内容都脱离硬件 DMA 路径。通过创建 VAO,您要么从错误配置的默认 VAO 切换,要么您正在尝试启用客户端 VAO 但被保存,因为客户端阵列已折旧并且在与 VAO 一起使用时不起作用(改为抛出 INVALID_OPERATION 错误) .

关于ios - 使用 VBO 的 OpenGL ES iOS 绘图性能比不使用 VBO 慢很多,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15297773/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com