Приложение вылетает после загрузки десятков текстур - PullRequest
1 голос
/ 08 января 2012

Я заметил, что когда я загружаю несколько десятков текстур, мое приложение вылетает без уведомления или около того.Он просто возвращается к предыдущему экрану телефона.Может быть потому, что телефон не может хранить столько памяти?Не стоит ли загружать все текстуры перед началом игры?

Ответы [ 2 ]

2 голосов
/ 08 января 2012

Вы уже получили свой ответ как часть комментариев, но я напишу здесь следующее заключение:

Размер ваших активов в хранилище не имеет значения, так как они, вероятно, сжаты.Важным является размер фактического рабочего набора.В случае изображений вы можете рассчитать его как

width * height * sizeof(pixel)

, где

sizeof(pixel) = sum[channels]{ sizeof(channel) }

В случае 1024x1024, 4 канала (RGBA), 1 байт на канал, размер вашего рабочего набора составляетодна текстура будет:

1024*1024 = 1Mi
1Mi * 4 * 1B = 4MiB

В случае 27 текстур это составит 27*4MiB = 108MiB.Теперь OpenGL определен в терминах абстрактной машины, что означает, что вы не можете спросить, сколько памяти у вас есть, чтобы потратить.Он просто скажет вам, если ему не хватает памяти.OpenGL также может использовать обычную системную RAM, если не все вписывается в видео RAM.В любом случае, на портативном устройстве вам, скорее всего, не хватит памяти, если вы попытаетесь загрузить более 100 МБ текстурных данных.

Стоит ли загружать все текстуры перед началом игры?

Нет, не стоит.На самом деле лучше «транслировать» содержимое вашей игры, загружать вещи по требованию.Также очень помогает какая-то схема сбора или переработки мусора.Выделение текстуры стоит дорого (то есть вызов glTexImage), тогда как замена данных стоит дешево (glTexSubImage), поэтому я предлагаю добавить «неиспользуемый» счетчик в вашу структуру управления текстурой.Каждый раз, когда вы связываете текстуру и рисуете ее, вы устанавливаете ее на ноль.После окончания кадра увеличивайте «неиспользуемый» счетчик каждого объекта текстуры.Если вам нужно загрузить новую текстуру, которую вы перебираете по всем объектам текстуры, выберите объекты с соответствующим форматом (одинакового размера и количества каналов), отсортированные по неиспользуемому счетчику, затем повторно используйте объект текстуры с медианой «неиспользованных» значенийв середине отсортированного набора «неиспользованные».Каждая «более высокая неиспользованная» текстура должна быть освобождена, остальные остаются резервными.Если вам нужно выделить более одной текстуры (скорее всего), сначала выделите из N медианных объектов.Используя эту стратегию, вы получаете готовый к использованию объект текстуры, а также время от времени освобождаете неиспользуемую память.

1 голос
/ 08 января 2012

Чтобы подытожить комментарии, выделив таким образом текстуры 27, в общей сложности 1024 на 1024 пикселя в режиме RGBA, вы выделяете 4 МБ видеопамяти каждый раз для каждой текстуры, в общей сложности 110 МБ.

Чтобы избежать такого рода сбоев и быть совместимым с несколькими системами Android, вы должны уменьшить размер текстур (иногда снижая общее качество).

Бесполезно говорить, что текстурыдолжны быть выгружены, если они больше не используются, чтобы освободить место для других новых нагрузок.

...