2012-03-10 5 views
4

Я использую 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); 
... 
+0

Не могли бы вы отправить код, который настраивает массивы атрибутов? Как быстрые, так и медленные версии? –

+1

Можете ли вы опубликовать свое решение в качестве ответа и принять его, чтобы другие знали, что эта проблема решена? –

ответ

0

Структура массивов для достижения единичного доступа в память - это эмпирическое правило. Он применяется не только для GPU, но и для CPUS и Co-процессоров, таких как Intel Xeon Phi.

В вашем случае я не верю, что эта часть кода отправляется на GPU, вместо этого потеря производительности связана с доступом к памяти без единого шага (CPU в/из памяти).

Смежные вопросы