Войти
ПрограммированиеФорумГрафика

glDeleteBuffers() и glDeleteTextures() не освобождают память (upd.: освобождают; опечатка - два одинаковых индекса, дважды создавался VAO, а удалялся только один)

Страницы: 1 2 3 4 Следующая »
#0
9:25, 24 янв. 2018

Собственно, проблема известная и давно гуглится. Но решения нет. Невозможно заставить драйвер освободить память, выделенную функциями glBufferData() и glTexImage2D().

Более того, в моем случае память не освобождается даже при уничтожении контекста!

    SDL_GL_DeleteContext(rs_app.sdl_ctx);
    sleep_msec(20000);
    SDL_DestroyWindow(rs_app.sdl_win);
    sleep_msec(50000);

Вывод massif выглядит вот так.
По шкале Х - время, измерятся в количестве выполненных млрд. инструкций.
По шкале Y - потребляемая память.
Последние столбцы с неизменным количеством потребляемой памяти, это тот самый sleep().

    MB
427.3^                                           #                            
     |                                           #                            
     |                                          @#                            
     |                                         :@# ::@::  :@::::::@:::::@:::::
     |                                    ::::::@#:::@:::::@::::::@:::::@:::::
     |                             @  @::::: :::@#:::@:::::@::::::@:::::@:::::
     |                       @ :@ @@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |                    @::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |               @: @:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |            :@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |           ::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |         @:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |      :::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@:::::
     |      :::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |   @:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |:::@:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |:::@:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |:::@:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |:::@:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
     |:::@:::::@:::@:@ :@:@::@::@:@@::@::::: :::@#:::@:::::@::::::@:::::@::::@
   0 +----------------------------------------------------------------------->Gi
     0                                                                   20.41

У меня тут генерируемый мир. При движении игрока старая геометрия за спиной игрока уничтожается, новая впереди создаётся. Но из-за того, что память при удалении не освобождается, через какое-то время память просто заканчивается и всё.

Пробовал передавать в glBufferData() пустой массив, не помогло.

Единственное, что приходит в голову - вместо удаления старых данных писать "поверх них" новые. Правда, не понятно, как поступать, если новых данных больше. Напрашивается мысль создавать по несколько мелких VBO, но у меня есть еще и индексы, которые не смогут "ссылаться" на чужой VBO. Избавиться от индексов, дублировать вершины и рисовать "в лоб" - должно сработать, но как-то все это нерационально.

У кого какие мысли на этот счет?

#1
9:50, 24 янв. 2018

под мобильным нет такой проблемы, там буфер ограничен 65k вершинами, потому приходится сразу думать об организации списка буферов
на остальных системах проще фрагментировать один или несколько буферов с более менее универсальными наборами атрибутов
в самых современных системах дополнительно снижены задержки на вывод множества однотипных объектов

и зачем что-то удалять во время игрового процесса ?

#2
10:18, 24 янв. 2018

glasm
> под мобильным нет такой проблемы, там буфер ограничен 65k вершинами
Серьёзно? А это где-то написано? У меня вершин мягко говоря побольше, чем 65к, ни разу о таком ограничении не слышал.

> и зачем что-то удалять во время игрового процесса ?
Ну я же написал. Игрок переместился в другую часть мира, старый кусок удаляем, новый загружаем (генерируем).

#3
10:28, 24 янв. 2018

glasm написал 24 янв. 2018:

под мобильным нет такой проблемы, там буфер ограничен 65k вершинами...

"Под мобильный" кем? Это точно сообщение из 2018го года, и кто-то ещё мучается поддержкой Android устройств 5-7милетней давности
(у которых давно умерла батарейка, даже если они сами по себе не превратились в пыль благодаря именитому качеству современных мобильных устройств)?

Роман Шувалов

Серьёзно? А это где-то написано? У меня вершин мягко говоря побольше, чем 65к, ни разу о таком ограничении не слышал.

OpenGL ES 2.0 с его буфером индексов из unsigned 16-bit integer (нормальные 32-битные индексы поддерживаются либо при наличии расширения, либо если устройство OpenGL ES 3.0+).
#4
10:32, 24 янв. 2018

Роман Шувалов

У меня тут генерируемый мир. При движении игрока старая геометрия за спиной игрока уничтожается, новая впереди создаётся.
Но из-за того, что память при удалении не освобождается, через какое-то время память просто заканчивается и всё.

Тут должно было быть написано, на чём всё это дело тестируется, воспроизводится ли проблема на разных конфигурациях (желательно с разным GPU) и полноценные куски кода вызывающие проблему.
Очевидно, что другие программы тоже создают и удаляют VBO, и как-то справляются с "память при удалении не освобождается" - то есть это либо бага в драйверах, бага в коде или особенности менеджера памяти конкретного OpenGL драйвера, которые воспринимаются как утечки.
#5
11:20, 24 янв. 2018

А зачем вообще чистить память после glBufferData?
Буфер попользовал, удалил. Та память, что после него осталась, становится ничейной и можно поверх данные накидывать, но уже для нового буфера, со своим glBufferData.

#6
11:23, 24 янв. 2018

gkv311
> Это точно сообщение из 2018го года
да, прикинь, на начало 2018 года ЛИШЬ 94% сотовых и 92% планшетов поддерживает 32-битные индексы, а 1/3 устройств не умеют GLES3, включая новые устройства на Android5+ на старых чипах

Роман Шувалов
> старый кусок удаляем, новый загружаем (генерируем).
что значит удаляем ? не рисуем буфер(ы) с кучей объединённых объектов или не рисуем отдельные объекты в той области ?
т.е. что проще, перезапонить буфер вершинами и индексами или обновить список отображаемых объектов... какой метод используется ?
если первый, то буфер, куда переходим, можно заполнять постепенно, а предыдущий просто "перемещаем" дальше, указав, что он пустой

#7
11:28, 24 янв. 2018

glasm

да, прикинь, на начало 2018 года 94% сотовых и 92% планшетов не поддерживает 32-битные индексы, а 1/3 устройств не умеют GLES3, включая новые устройства на Android5+ на старых чипах

Пруфы в студию.
#8
11:34, 24 янв. 2018

https://webglstats.com/webgl/extension/OES_element_index_uint
https://developer.android.com/about/dashboards/index.html

#9
11:47, 24 янв. 2018

может vulkan  ?

#10
13:30, 24 янв. 2018

Для начала скажу, что любой при нехватки памяти всё наглухо виснет. Речь не только про мою разработку, а про любое приложение. По треску HDD предполагаю, что система пытается задействовать своп, хотя своп-раздела у меня не размечено. Спасает только Хард Ресет, хотя иногда отвисает пометкой "Bus error". Но редко. Разбираться с этим как-то руки не дошли.

gkv311
> OpenGL ES 2.0 с его буфером индексов из unsigned 16-bit integer
Ясно. Буду иметь в виду, спасибо.

> Тут должно было быть написано, на чём всё это дело тестируется, воспроизводится ли проблема на разных конфигурациях
ПК, Linux, Intel HD4000. Сегодня протестирую на другом ПК, но сильно сомневаюсь, что ситуация изменится. Даже если изменится, приемлимый "workaround" надо искать и на моём текущем железе.

> и полноценные куски кода вызывающие проблему

glBindBuffer(GL_ARRAY_BUFFER, vboid);
glBufferData(GL_ARRAY_BUFFER, data_len, data, GL_STATIC_DRAW);
// Потрачено data_len байтов
glDeleteBuffers(1, &vboid);
// data_len байтов не освободилось и никогда не будет освобождено. 

gkv311
> Очевидно, что другие программы тоже создают и удаляют VBO, и как-то справляются с "память при удалении не освобождается"
Ну, может им хватает памяти даже с учетом того, что память не освободилась. Но иногда не хватает и всё виснет. Team Fortress 2, помнится, вис, до тех пор пока с течением времени не распух до такой степени, что моё железо перестало его тянуть.

PA3UJIb
> Буфер попользовал, удалил. Та память, что после него осталась, становится
> ничейной и можно поверх данные накидывать, но уже для нового буфера, со своим glBufferData.
В том-то и дело, что эта "ничейная" память на деле не используется и только занимает место. И новые вызовы glBufferData располагаются в новых кусках памяти, а старый висит мёртвым грузом.

innuendo
> может vulkan ?
На изучение нового GAPI и переписыванию всей игры, мягко говоря, нет времени.

#11
13:48, 24 янв. 2018

сделать контекст точно текущим в этом потоке.
убедиться что ошибки нет
glBindBuffer(GL_ARRAY_BUFFER, vboid);
glBufferData(GL_ARRAY_BUFFER,0, 0, GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);
уже потом удалить,
удаление текущего буфера может плохо кончиться

#12
15:06, 24 янв. 2018

Да ёшкин крот! Проблема исчезла! Всё успешно удаляется. Успех был обнаружен после кода ShadowTeolog, но теперь я его стёр и вернул все как было (даже не биндю нулевой буфер) - всё равно все успешно удаляется. Либо я действительно где-то что-то тронул и все само заработало, либо драйвер надо мной издевается.

upd.: Вероятно, я в процессе отладки включил контекст GL2, в нём не использовался VAO, а именно VAO оказался источником проблемы.

#13
15:11, 24 янв. 2018

glasm
> да, прикинь, на начало 2018 года 94% сотовых и 92% планшетов не поддерживает 32-битные индексы, а 1/3 устройств не умеют GLES3, включая новые устройства на Android5+ на старых чипах
> https://webglstats.com/webgl/extension/OES_element_index_uint
++


Кстати, у Vulkan поддержка 32 битных индеков достпуна только при наличии флага VkPhysicalDeviceFeatures::fullDrawIndexUint32, так что тут все от железа зависит.
Пример устройства которое дежит 32 битные индексы на OpenGL ES 3x, но не держит на Vulkan:
https://vulkan.gpuinfo.org/displayreport.php?id=2359#features

#14
19:08, 24 янв. 2018

Роман Шувалов
Ставиш CodeXL. Ставишь галки на:
Break on OpenGL Error
Break on Detected Error
Break on Memory Leaks

+ Показать

Запускаешь, играешь, корректно выходишь из игры. Узнаешь много нового. :)
Страницы: 1 2 3 4 Следующая »
ПрограммированиеФорумГрафика

Тема в архиве.