Я использую MacMini '11 с AMD Radeon HD 6630M. Я рисую сетку, используя структуру массивов, и все хорошо: 60 кадров в секунду (с использованием CVDisplayLink). Я использую шейдер со встроенными атрибутами. Жизнь хороша. Я перехожу к использованию массива структур (чередующихся), потому что я понимаю, что это предпочтительнее для «современных» графических процессоров. Атрибуты определены в шейдере. Сетка красиво рисуется. Но когда я это делаю, частота кадров падает примерно на 33% (до 40 кадров в секунду). И есть несколько копий этих вызовов. Использование инструментов: 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]);
}
}
Update: После дальнейшего исследования: 1) Я использую modelObj загрузчик dhpoWare в (модифицированном) и, поскольку она использует перемежаемый массив структур, он также действует как мой массив структур по производительности - просто не так, как бит. Возможно, я неправильно интерпретирую инструменты. Код modelObj вызывает вызов glDrawElements_IMM_Exec, он также в кольцевом режиме вызывает gleDoDrawDispatchCore. Я не уверен, что он просто накапливает кучу вызовов в glDrawElements_IMM_Exec, а затем взрывает их через gleDoDrawDispatchCore. Не знаю. 2) Я думаю, что у инструментов есть проблемы, так как он показывает, что GLEngine вызывает один из моих неиспользуемых внутренних методов объектов 3ds, который не имеет внешних крючков. Я дважды проверил, установив там точку останова Xcode, и она никогда не срабатывала. Я больше не занимаюсь 3DS.
Думаю, я продолжу оглядываться и, возможно, споткнуться о ответ. Если бы кто-то дал мне мнение о том, может ли быть массив структур, это было бы оценено.
РЕШЕНИЕ: Я добавил VBO к переднему концу этого, и все хорошо. Исходный код пришел из руководства OpenGL ES 2.0, и добавление VBO исправляет мою проблему. Частота кадров при вызовах драйвера 60, 1 мс. Вот код:
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);
...
Не могли бы вы отправить код, который настраивает массивы атрибутов? Как быстрые, так и медленные версии? –
Можете ли вы опубликовать свое решение в качестве ответа и принять его, чтобы другие знали, что эта проблема решена? –