2012-05-30 4 views
2

Я написал быстрое приложение, чтобы понять рамки RenderScript и распознал, что при достижении примерно 65 000 треугольников система просто не рисует никаких дополнительных. Например, если я создаю цилиндр с 70 000 треугольников, из цилиндра будет отсутствовать клин, соответствующий треугольникам, которые превышают отметку ~ 65 000. Треугольники текстурированы и для удобства написания приложения я просто использовал класс TriangleMeshBuilder, поэтому нет реальной оптимизации, например, с использованием трифанов или триплетов. Аппаратное обеспечение Samsung Galaxy Nexus. LogCat сообщает о размере кучи около 15 МБ с 3% бесплатной. Я не получаю никаких ошибок или предупреждений относительно графической системы или RenderScript.Максимальное количество треугольников в RenderScript

Может ли кто-нибудь объяснить причину падения треугольников? Я на аппаратном лимите, который RenderScript обрабатывает изящно?

ОБНОВЛЕНИЕ Происходит на Samsung Galaxy Nexus (4.0.3), Samsung Galaxy Tab 7.0+ (3.2) и Motorola Xoom (3.2). Все в одной точке примерно 65 000 треугольников. Каждое из этих устройств имеет разные графические процессоры.

ОБНОВЛЕНИЕ 2 В ответ на мысли Стива Блэквелла у меня есть дополнительные мысли.

Линии 710-712 действительно понижают показатели int до short, таким образом, 65536 уходит в 0, поскольку Стив указывает. Кроме того, «литье» в строке 757 - это не столько актеры, сколько указание RenderScript на формат двоичных данных, которые в конечном итоге будут отправлены на него. RenderScript требует, чтобы все данные были упакованы в определенный тип данных RenderScript, называемый Allocation, для перехода от Java к среде выполнения RenderScript, и об этом необходимо сообщить в отношении структуры данных. В соответствии со взглядом Стива, что это ошибка, строка 757 сообщает RenderScript для обработки данных индекса как short (без знака 16 бит), но он отправляет ему 32-битное знаковое значение (которое будет принято из-за отсутствия проверки и обработки без знака , а затем используются только младшие 16 бит, поэтому мы получаем что-то, когда ниже этого порога и треугольники соединяются с первыми индексами, когда мы переходим).

Подкласс TriangleMeshBuilder, чтобы увидеть, могу ли я заставить его принимать эти значения как целые числа, чтобы увеличить этот предел, не сработало, что заставляет меня думать, что где-то в глубоком коде, к которому у нас нет доступа, есть дополнительная ссылка к неподписанным шортам. Похоже, единственная работа - добавить дополнительные буферы вершин, которые предлагает Стив, что легко сделать с существующим классом Mesh.AllocationBuilder. Я также расскажу об этом в Google Hangouts для разработчиков, чтобы определить, является ли это на самом деле ошибкой или преднамеренным.

+0

Вы пробовали это на других устройствах? –

ответ

3

Я ничего не знаю о RenderScript, поэтому я не знаю, является ли это неотъемлемым ограничением, аппаратной проблемой или чем-то связанным с TriangleMeshBuilder, но я бы поспорил, что у вас закончились треугольники после номера 65535

Это магическое число, потому что это максимальное значение беззнакового 16-битного целого. (Wikipedia)

Я подозреваю, что где-то в коде есть unsigned short, который содержит количество треугольников. Это не будет в коде Java, так как Java не имеет неподписанных значений. И ограничение, вероятно, не аппаратное, так как регистры/пути CPU> = 32-бит. Поэтому я бы проверил TriangleMeshBuilder.

EDIT:

Это большая находка на line 553. Значение каждого индекса должно соответствовать short.Похоже, что понижение происходит на line 710-712.

Предполагаю, что вы звоните addTriangle(). Эта функция принимает три int s, а затем делает явное приведение к short. Я думаю, что это ошибка там, потому что подавление происходит тихо, и это не то, что вы ожидаете от сигнатуры функции.

На line 768 данные фиктивных данных переходят на Allocation.copy1DRangeFromUnchecked(). Я не следовал за этим до конца, но я предполагаю, что в какой-то момент эти подписанные значения будут отличать без знака: от -32768 до -1 возвращается обратно в 32768 до 65535. Таким образом, превращение индексов в негативы выглядит плохо, но это просто переинтерпретация одних и тех же данных, и это не проблема.

Настоящая проблема возникает, когда вы отправляете значения, такие как 65536. Когда 65536 отлита до short, она превращается в 0. Это настоящая потеря данных. Теперь вы имеете в виду разные индексы, и приведение в unsigned не исправит.

Настоящий кикер состоит в том, что copy1DRangeFromUnchecked() является перегруженной функцией и одним из overloads takes an int[], поэтому ничто из этого не должно было быть проблемой.

Для обходных решений, я думаю, вы могли бы подкласса TriangleMeshBuilder и переопределить переменную-член mIndexData[] и метод addTriangle(). Или, может быть, вы можете использовать несколько вершинных буферов. Или зарегистрировать отчет об ошибке где-нибудь? Во всяком случае, интересная проблема.

+0

Это не может быть в TriangleMeshBuilder, потому что это также Java, но поскольку RenderScript написан на C99, вполне вероятно, что так будет. Я чувствую себя глупо, что не понимаю, что я был рядом с этим порогом, тем более что мне пришло в голову, что я был ниже 32-битного предела. Я попытаюсь взглянуть на код C и посмотреть, всплывает ли что-нибудь. – Jared

+0

Я просто взглянул и определил тип соответствующих типов данных RenderScript, и все они используют 32-битные целые числа без знака. Первоначально я подозревал бы (пожалуйста, поправьте меня, если я ошибаюсь), что это не проблема, однако у меня нет способа взглянуть на фактический источник RenderScript (только файлы заголовков). – Jared

+0

Я действительно не знаю, куда идти отсюда. Если у вас есть код, который вы хотите показать, или если вы можете указать пример, который вы используете, это может помочь, но я немного из моей лиги с RenderScript. –

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