Программирование игр, создание игрового движка, OpenGL, DirectX, физика, форум
GameDev.ru / Программирование / Форум / glDeleteBuffers() и glDeleteTextures() не освобождают память (upd.: освобождают; опечатка - два одинаковых индекса, дважды создавался VAO, а удалялся только один) (2 стр)

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

Страницы: 1 2 3 4 Следующая »
Роман ШуваловУчастникwww20 мар. 201813:04#15
Проблема вернулась (уже давно, но разбираться начинаю только сейчас).

Теперь у меня в распоряжении не только Debian, но и Windows 10.

MrShoor
> Ставиш CodeXL.
> Узнаешь много нового. :)

> SDL_GL_DeleteContext(rs_app.sdl_ctx);
Memory Leak: 139 object(s) are leaked in GL Context 2 (Leak Size: 164KB)

Ничего нового не узнал. CodeXL даже не показал то, что показывал valgrind:

==2051== 87,277,568 bytes in 20 blocks are definitely lost in loss record 696 of 696
==2051==    at 0x10042960: ??? (in /usr/lib/x86_64-linux-gnu/libdrm_intel.so.1.0.0)
==2051==    by 0xFB32B5B: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so)
==2051==    by 0xFB31C7C: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so)
==2051==    by 0xF89EB36: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so)
==2051==    by 0xF89F92F: ??? (in /usr/lib/x86_64-linux-gnu/dri/i965_dri.so)
==2051==    by 0x1622C1: rs_tx_create_from_data (rstexture.c:522)
==2051==    by 0x162160: rs_tx_create_png_adv (rstexture.c:451)
==2051==    by 0x180F16: game_loader_check_texture_mainthread (loader.c:1222)
==2051==    by 0x16EFE6: GameProcess (game.c:908)
==2051==    by 0x15C9A6: rs_app_process (rsplatform_sdl.c:1057)
==2051==    by 0x15C86A: rs_app_loop (rsplatform_sdl.c:936)
==2051==    by 0x1852D3: main (main.c:133)

В Windows 10 проблема такая же. Память не особождается, в диспетчере задач вижу все больше и больше пожирания RAM и в какой-то момент все вылетает.

foxesПостоялецwww20 мар. 201813:28#16
Роман Шувалов
> Leak Size: 164KB
А какого объема сами буферы? Мне кажется что это связанно не с выделением удалением буфера, а со структурами их сопровождающие.
Или каждый из 139 объектов имеет размер по 164KB?
И вообще эти самые буферы разве не на стороне видеокарты алоцируются?

Правка: 20 мар. 2018 13:32

Роман ШуваловУчастникwww20 мар. 201813:45#17
foxes
164 кб - думаю, это общее, что смог найти CodeXL на стороне видеокарты.

А так - потребление ОЗУ до вызова SDL_GL_DeleteContext() составляет порядка 800 Мб, после вызова - порядка 150 Мб (это мои данные). То есть 650 Мб в процессе работы потеряны, но освобождены при удалении контекста. А мне их надо освободить вручную, т.к. эта цифра постоянно растет с загрузкой новых объектов.

foxes
> И вообще эти самые буферы разве не на стороне видеокарты алоцируются?
Тут два варианта: либо все, что работает на стороне видеокарты, успешно выделяется и освобождается, а драйвер мусорит в ОЗУ, либо система в диспетчере задач в графе потребления ОЗУ показывает и видеопамять, т.к. я работаю на встроенном Интеле и видеопамять там выделяется из основной памяти.

Роман ШуваловУчастникwww20 мар. 201814:36#18
Вот, смотрите, какая красота.
    MB
737.9^                                                                                                                 #
     |                                                                                                  @      @:      #
     |                                                                                   @       @:     @:     @:     :#
     |                                                                            @@:    @:     :@:    :@:    :@:    ::#
     |                                                              ::      ::    @ :   :@:    ::@:    :@:   ::@:  ::::#
     |                                                ::     :     ::     :::     @ :  ::@:   :::@:  :::@:  :::@: :::::#
     |                                  :     ::    :::     ::     ::     : :   @@@ : :::@:  ::::@: ::::@::::::@:::::::#
     |                  @::     :    ::::    ::     : :   ::::   @@::   ::: : ::@ @ :::::@:::::::@::::::@::::::@:::::::#
     |            @@    @:    :::    :  :  ::::   ::: :  :: ::  :@ :: ::: : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |          ::@   @@@:   :: :   ::  :  : ::   : : : ::: :::::@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |         :: @   @ @:  ::: : ::::  :::: :: ::: : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |       :::: @ ::@ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |      :: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |     ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |     ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     |  :::::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     | ::  ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     | ::  ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     | ::  ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
     | ::  ::: :: @ : @ @: :::: :@: ::  :: : :: : : : : ::: ::: :@ :: : : : : : @ @ :::::@:::::::@::::::@::::::@:::::::#
   0 +----------------------------------------------------------------------------------------------------------------->Gi
     0                                                                                                             144.2

Это я в цикле поставил загрузку-выгрузку всей геометрии. Видны скачки (выделение памяти) и падения (освобождение памяти), но потихонечку все ползет вверх. Где утечка? valgrind показывает, что кроме разовых glTexImage2D утечек нет. CodeXL говорит, что после уничтожения контекста утечек наберется на сколько-то там жалких килобайт, это к делу не относится. И как ловить такое?

Роман ШуваловУчастникwww20 мар. 201814:42#19
Поизучал вывод massif...

Вызовы, отвечающие за создание VBO, сначала занимают ~200 Мб, а к концу графика ~300 Мб. Похоже виноват всё-таки я. Это обнадёживает.

Тааак, а если выключить VAO, то всё в порядке:

    MB
362.3^         ##                                                                                                       
     |         #                                                                                                        
     |         #                            ::  ::   ::   ::::         ::   ::                   @        : @@ :     :  
     |         #   :::::@@::  ::::::     :::: @@: :::: ::::  ::::::::::: :::: ::  ::: ::@@@::::: @::::::::::@ :::::::::@
     |     @:::# :::: : @ : ::::  : :::::: :: @ : : :: : ::  ::: :: : :: : :: : :::: :: @  ::::::@: ::::::::@ :::::::::@
     |   ::@: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     |   : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     |   : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     |   : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     |   : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | ::: @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
     | : : @: :# : :: : @ : : ::  : : :: : :: @ : : :: : ::  ::: :: : :: : :: : : :: :: @  ::::::@: ::::::::@ :::::::::@
   0 +----------------------------------------------------------------------------------------------------------------->Gi
     0                                                                                                             201.6

Причем в случае с VAO massif приписывает выделение памяти на строке с glGenVertexArrays(), что немного странно, данные-то в видеопамяти создаются вызовом glBufferData().

Правка: 20 мар. 2018 15:44

Роман ШуваловУчастникwww20 мар. 201816:09#20
Значит так.

Massif считает, что вот на этой строчке:

glGenVertexArrays(1, &(vaoid[ sh ]));
суммарно со всех вызовов выделяется много памяти, причем с каждой итерацией памяти выделяется все больше и больше (очевидно, часть её не освобождается).

Собственно, вопрос - как грамотно удалить VBO вместе с VAO и всем остальным причитающимся?

Сейчас у меня так:

glBindVertexArray(0);  
for (int i = 0; i < RS_MAX_SHADERS; i++) {
    if ( vaoid[i] ) {
        glDeleteVertexArrays(1, &(vaoid[i])); // (было создано несколько VAO для каждого шейдера, который использует модель)
    };
};

glBindBuffer(GL_ARRAY_BUFFER, 0); 

glDeleteBuffers(1, &(vboid));
vboid = 0;

if (iboid) {
    glDeleteBuffers(1, &(iboid));
    iboid = 0;
};

Правка: 20 мар. 2018 16:19

foxesПостоялецwww20 мар. 201816:29#21
Роман Шувалов
> glGenVertexArrays(1, &(vaoid[ sh ]));
Технически эта операция ни чего не делает относительно самой видеокарты. Как раз таки на стороне процессора и размещенного в оперативной памяти контекста, в массив объектов вершин добавляется новый элемент с описанием всех связанных с вершинами данных. Например адрес выделенной в видеопамяти области. Удалятся этот элемент должен сам при удалении контекста. Но это небольшая структурка с парой полей.

Роман Шувалов
> суммарно со всех вызовов выделяется много памяти, причем с каждой итерацией
> памяти выделяется все больше и больше (очевидно, часть её не освобождается).
Сам массив элементов видимо распределяется с заранее выделением дополнительного места, как в случае с выделением области под массив кратный степеням двойки. Но также должно освобождаться то что выделялось ранее. Ты случаем не затер какую нибудь область памяти где был указатель на метод с удалением памяти?

Роман Шувалов
> glDeleteBuffers(1, &(vboid));
Не сразу прочитал, но тут если vboid это массив, то это касяк однозначно.

Правка: 20 мар. 2018 16:40

Роман ШуваловУчастникwww20 мар. 201816:45#22
Кстати, спрошу-ка я между делом... я вообще правильно делаю, что создаю VAO для каждого объекта? Я тут посморел - он же (вроде) не имеет привязки к VBO, а содержит только информацию о том, как к этому VBO обращаться. Может, правильно будет создать один VAO для всех однотипных моделей? А при догрузке/удалении моделей оперировать только VBO?

foxes
> Не сразу прочитал, но тут если vboid это массив, то это касяк однозначно.
Нет, массив толко vaoid, т.к. он свой для каждого шейдера. vboid и iboid - просто числа GLuint.

Правка: 20 мар. 2018 16:46

Роман ШуваловУчастникwww20 мар. 201816:52#23
P.S. На мысль о том, что VAO вообще удалять не нужно, навело вот вот это:
https://stackoverflow.com/questions/41520764/should-i-delete-vert… array-objects
2.6.1.2 Name Deletion and Object Deletion

If an object is deleted while it is currently in use by a GL context, its name is immediately marked as unused, and some types of objects are automatically unbound from binding points in the current context, as described in section 5.1.2. However, the actual underlying object is not deleted until it is no longer in use. This situation is discussed in more detail in section 5.1.3.

5.1.2 Automatic Unbinding of Deleted Objects

When a buffer, texture, or renderbuffer object is deleted, it is unbound from any bind points it is bound to in the current context, and detached from any attachments of container objects that are bound to the current context, as described for DeleteBuffers, DeleteTextures, and DeleteRenderbuffers. [...] Attachments to unbound container objects, such as deletion of a buffer attached to a vertex array object which is not bound to the context, are not affected and continue to act as references on the deleted object, as described in the following section.

foxesПостоялецwww20 мар. 201816:54#24
Роман Шувалов
> Кстати, спрошу-ка я между делом... я вообще правильно делаю, что создаю VAO для
> каждого объекта?
Я вообще не знаю зачем ты это делаешь честно. вот мой код:
void _FASTCALL Render::_UpdateModelElementVBO(Mesh *model,VBOMesh *vbo,int _id,int _count)
{  
  sFunctionsGLContext &functions=GlContext::p_current->functions();
  int s=Mesh::_elementSize(model->p_elementFormat);
  if (!vbo->elements) {
    functions.GenBuffers(1,&vbo->elements);
    functions.BindBuffer(GL_ARRAY_BUFFER_ARB,vbo->elements);
    functions.BufferData(GL_ARRAY_BUFFER_ARB,s*model->p_elementCount,(GLvoid *)model->p_elements,GL_DYNAMIC_DRAW_ARB);
  } else {
    unsigned char *p=model->p_elements;
    _id=_id*s;
    p+=_id;
    functions.BindBuffer(GL_ARRAY_BUFFER_ARB,vbo->elements);
    functions.BufferSubData(GL_ARRAY_BUFFER_ARB,_id,s*_count,(GLvoid *)p);
  }
}

void _FASTCALL Render::_UpdateModelIndexVBO(Mesh *model,VBOMesh *vbo,int _id,int _count)
{  
  sFunctionsGLContext &functions=GlContext::p_current->functions();
  if (!vbo->index) {
    functions.GenBuffers(1,&vbo->index);
    functions.BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,vbo->index);
    functions.BufferData(GL_ELEMENT_ARRAY_BUFFER_ARB,(sizeof(GlIndex))*model->p_indexCount,(GLvoid *)model->p_index,GL_DYNAMIC_DRAW_ARB);
  } else {
    unsigned int *p=(unsigned int *)model->p_index;
    p+=_id;
    _id=_id*4;
    functions.BindBuffer(GL_ELEMENT_ARRAY_BUFFER_ARB,vbo->index);
    functions.BufferSubData(GL_ELEMENT_ARRAY_BUFFER_ARB,_id,_count*(sizeof(GlIndex)),(GLvoid *)p);
  }
}
void _FASTCALL Render::FreeVBO(VBOMesh *mesh)
{
  Context_P * mcontext=(Context_P *)(GlContext::p_current->p_context);
  if (mcontext->_GL_ARB_vertex_buffer_object) {
    if (mesh->index) mcontext->glDeleteBuffers(1,&mesh->index);
    if (mesh->elements) mcontext->glDeleteBuffers(1,&mesh->elements);
    mesh->index=0;
    mesh->elements=0;
  }
}

Правка: 20 мар. 2018 16:56

Роман ШуваловУчастникwww20 мар. 201817:06#25
foxes
> Я вообще не знаю зачем ты это делаешь честно. вот мой код:
Мой код был примерно таким же до перехода на OpenGL 3.0, где использование VAO строго обязательно. Но я изучал его впопыхах и видать не понял, нужно ли для каждого VBO создавать свой VAO или можно один раз создать по одному VAO для каждого типа объектов, а VBO потом хоть сотнями грузить.
foxesПостоялецwww20 мар. 201817:35#26
А разве VAO не был всегда альтернативой и не более?
Когда я ковырялся в одном драйвере, VAO было составной часть VBO, но явно им управлять не приходилось.

Правка: 20 мар. 2018 17:36

Роман ШуваловУчастникwww20 мар. 201817:46#27
foxes
Нет, в OpenGL 3.0 использование "нулевого" VAO (читай: неиспользование его) стало deprecated, а начиная с 3.3 возможность не использовать VAO убрана. То есть VAO использовать обязательно.

foxes
> ковырялся в одном драйвере, VAO было составной часть VBO, но явно им управлять не приходилось.
А я вот также и сделал, при создании VBO создается VAO и я работаю просто с моделью. Но VAO, как я вижу, нельзя нормально удалить. Отсюда и начались вопросы.

Правка: 20 мар. 2018 17:47

DampireУчастникwww20 мар. 201818:15#28
Роман Шувалов
Сделай один, чтобы эмулировать старый функционал. В чем проблема?
foxesПостоялецwww20 мар. 201818:21#29
Я немного не про то. Смысл в том что VBO используется как буфер индексов, а VAO как буфер вершин, и в место VAO также используется VBO другой. Они просто биндятся по разному через GL_ELEMENT_ARRAY_BUFFER_ARB и GL_ARRAY_BUFFER_ARB соответственно.

Просто в твоей версии для GL_ARRAY_BUFFER_ARB подходит только VAO, то есть уже glBindVertexArray

Правка: 20 мар. 2018 18:28

Страницы: 1 2 3 4 Следующая »

/ Форум / Программирование игр / Графика

2001—2018 © GameDev.ru — Разработка игр