OpenGL ES 2.0 на iPhone: невозможно превысить небольшой индекс / количество вершин - PullRequest
1 голос
/ 31 августа 2011

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

Ряд индексов, начинающихся с нуля, используется для 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?

UPDATE

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

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

ОБНОВЛЕНИЕ 2

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

1 Ответ

3 голосов
/ 01 сентября 2011

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

...