OpenGL ES 2.0 на iPhone: невозможно превысить количество малых индексов / вершин

Я постараюсь быть кратким: я использую OpenGL ES 2.0 на iPhone, и я использую объект буфера вершин для одновременного рендеринга множества фигур на экране.

Для GL_ELEMENT_ARRAY_BUFFER используется серия индексов с нулем вверх, они хранятся в:

GLushort *ixData;

У каждой формы есть количество вершин. При создании новой формы общее количество вершин vxCount используется для перераспределения памяти для ixData:

NSLog(@"allocating ixData for %i shapes, %i vertices",shapes.size(),vxCount);
ixData = (GLushort*)realloc(ixData, vxCount*sizeof(GLushort));

Конечно, для ixData есть начальный malloc.

Каждая форма имеет 6 атрибутов вершин (2 положения, 4 цвета), и все они GLfloat. У каждой формы всего 24 вершины. Фигуры хранятся в vector<Shape>, поскольку код написан на C ++. Значение vxCount вычисляется путем умножения размера этого вектора фигур на количество вершин на фигуру (т. Е. shapes.size()*24).

Положение каждой формы меняется каждый кадр, поэтому я повторно отправляю данные буфера непосредственно перед вызовом glDrawElements при каждом рендеринге:

glBindBuffer(GL_ARRAY_BUFFER, buffers[0]);
glBufferData(GL_ARRAY_BUFFER, vxDataSize, vxData, GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffers[1]);
NSLog(@"render vxcount is %i",vxCount);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, ixDataSize, ixData, GL_STATIC_DRAW); //*

Приложение отлично работает с любым количеством фигур до 508 включительно. Однако, когда я пытаюсь добавить 509-ю фигуру, я получаю EXC_BAD_ACCESS для данных буфера индексов; в приведенном выше коде соответствующая строка помечена звездочкой.

Распечатки NSLog в приведенном выше коде показаны ниже. Как видите, последнее количество выделенных вершин согласуется с подсчетом при отправке индексов примитивов.

...

2011-08-31 20: 35: 59.438 nibfree [26409: 707] размещение ixData для 503 фигур, 12072 вершин

2011-08-31 20: 35: 59.441 nibfree [26409: 707] выделение ixData для 504 фигур, 12096 вершин

2011-08-31 20: 35: 59.444 nibfree [26409: 707] размещение ixData для 505 форм, 12120 вершин

2011-08-31 20: 35: 59.448 nibfree [26409: 707] размещение ixData для 506 фигур, 12144 вершин

2011-08-31 20: 35: 59.451 nibfree [26409: 707] размещение ixData для 507 фигур, 12168 вершин

2011-08-31 20: 35: 59.454 nibfree [26409: 707] размещение ixData для 508 фигур, 12192 вершин

2011-08-31 20: 35: 59.457 nibfree [26409: 707] размещение ixData для 509 фигур, 12216 вершин

2011-08-31 20: 35: 59.746 nibfree [26409: 707] рендеринг vxcount - 12216

~ 12k вершин не должно быть проблемой для устройства, а тип индексных данных GLushort означает, что индексы вершин 0-65535 должны быть возможны.

Я действительно в тупике, может ли кто-нибудь предположить, что пошло не так? Я превышаю ограничение буфера вершин / индекса, специфичное для iPhone?

ОБНОВЛЕНИЕ

Чтобы добавить ясности, я уменьшил размер фигуры вдвое с 24 до 12. Затем я попытался снова и достиг предела 1536 shapes, 18432 vertices. Если я попытаюсь добавить 1537 фигур с 12 вершинами на фигуру, она вылетит, как и раньше, с EXC_BAD_ACCESS.

Этот последний тест показывает, что хранилище vxData / ixData не является проблемой, и нет ограниченного количества вершин или индексов вершин. Возможное количество форм увеличилось примерно в 3 раза - означает ли это, что я столкнулся с особенностями рендеринга GL_TRIANGLES? А может это неправильное использование перераспределения? Я правда не понимаю, почему это проблема :(

ОБНОВЛЕНИЕ 2

Другой набор чисел для определения паттерна: 300 вершин имеют максимум 61 форму, 62 вызывает сбой. На 62 есть vxcount 18300, последний индекс ixData 18299, как и ожидалось.


person KomodoDave    schedule 31.08.2011    source источник
comment
Совершенно несвязанный комментарий: если ваши фигуры только перемещаются (и не получают больше или меньше), вам не нужно повторно копировать данные индекса в буфер каждый кадр.   -  person Christian Rau    schedule 01.09.2011
comment
Спасибо за подсказку по оптимизации, Кристиан, буду иметь это в виду :)   -  person KomodoDave    schedule 01.09.2011
comment
Есть ли вероятность, что ixDataSize получит неверное значение, превышающее vxCount*sizeof(GLushort)?   -  person Tommy    schedule 01.09.2011
comment
@Tommy - я люблю тебя. У меня случайно оказался vxCount * sizeof (GLuint). Если вы скопируете это в ответ, я поставлю вам галочку :)   -  person KomodoDave    schedule 01.09.2011
comment
Я сделал именно это, с забавной расширенной экспозицией.   -  person Tommy    schedule 01.09.2011
comment
Прежде чем рисовать, убедитесь, что ixData находится в диапазоне: for (size_t i=0; i<ixDataLen; i++) assert(ixData[i]<vxCount);   -  person Justicle    schedule 01.09.2011


Ответы (1)


EXC_BAD_ACCESS при загрузке, вероятно, вызван тем, что драйвер GL пытается прочитать память, которой ваше приложение не владеет. Поэтому вполне вероятно, что ваш ixDataSize имеет значение больше vxCount*sizeof(GLushort). Такая проблема могла остаться незамеченной с меньшими размерами буфера, потому что ixDataSize, который вы придумываете в этих случаях, не работает за пределами области, предоставленной вашему приложению, и, поскольку он больше, чем число, которое вы действительно хотите, все данные вы продолжаете использовать, скопировано.

person Tommy    schedule 31.08.2011
comment
Еще раз спасибо, Томми;) Веселая расширенная экспозиция была очень приятной. - person KomodoDave; 01.09.2011