Производительность массива структур или структуры массивов - PullRequest
4 голосов
/ 11 марта 2012

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

Обновление: После дальнейшего изучения: 1) Я использую загрузчик modelObj dhpoWare (модифицированный) итак как он использует чередующийся массив структур, он также действует как мой массив структур с точки зрения производительности - просто не такой уж хит.Возможно, я неправильно интерпретирую инструменты.Код modelObj вызывает glDrawElements_IMM_Exec, он также окольным путем вызывает gleDoDrawDispatchCore.Я не уверен, что он просто накапливает несколько вызовов в glDrawElements_IMM_Exec, а затем уничтожает их через gleDoDrawDispatchCore.Не знаю.2) Я думаю, что у Instruments есть проблемы, поскольку он показывает, что 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);
...

1 Ответ

0 голосов
/ 14 марта 2014

Структура массивов для достижения единичного доступа в память - это правило большого пальца. Это относится не только к графическим процессорам, но и к CPUS и сопроцессорам, таким как Intel Xeon Phi.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...