2015-01-14 4 views
6

У меня есть следующий рабочий код, однако я не уверен, что я вызываю glDeleteBuffers безопасным способом. На практике это работает (на данный момент, по крайней мере), но из того, что я читал, я не думаю, что он должен работать.Когда мне следует позвонить glDeleteBuffers()?

GLuint vao_id; 
glGenVertexArrays(1, &vao_id); 
glBindVertexArray(vao_id); 

GLuint VBO; 
glGenBuffers(1, &VBO); 
glBindBuffer(GL_ARRAY_BUFFER, VBO); 
glBufferData(GL_ARRAY_BUFFER, size, data, GL_STATIC_DRAW); 

glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, (void*)0); 
glEnableVertexAttribArray(0); 

    //Alternate position <<---- 

//Unbind the VAO 
glBindVertexArray(0); 

//Current position <<---- 
glDeleteBuffers(1, &VBO); 

В настоящее время я вызываю glDeleteBuffers прямо после развязывания VAO. Я попробовал называть его в альтернативной позиции, помеченной - сразу после того, как я установил указатель на атрибут. Это, однако, вызвало крах - я предполагаю, что это было потому, что, когда я сделал призыв к розыгрышу, никаких данных не было, потому что я удалил его.

Вещь, которая меня смущает, заключается в том, что она работает, как я ее сейчас. Я беспокоюсь, что: а) я не совсем понимаю, что происходит, когда буфер удаляется, и б) он работает только случайно и может неожиданно сломаться.

Насколько я понимаю, вызов glDeleteBuffers удаляет данные, поэтому не должно быть никаких данных для рисования - но есть. Моя другая мысль заключалась в том, что когда я перевязываю VAO, данные восстанавливаются, хотя это не имеет большого смысла для меня, потому что я не могу объяснить, откуда будут восстанавливаться данные.

Может ли кто-нибудь сообщить мне, правильно ли я использую glDeleteBuffer? и если не там, где это должно быть вызвано (я предполагаю, что нет необходимости в том, чтобы данные были сделаны больше, возможно, в конце программы).

ответ

11

Что вы видите, это четко определенное поведение. Ниже перечислены ключевые части спецификации, связанные с этим (выделено мной).

В разделе «5.1.2 Автоматическая развязывание удаленных объектов» в OpenGL 4.5 спецификации:

Когда буфер, текстуры, или renderbuffer объект удаляется, то несвязанными с любых точек связывания он является связанный в текущем контексте и , отдельно от любых вложений объектов контейнера, привязанных к текущему контексту, как описано для DeleteBuffers, DeleteTextures и DeleteRenderbuffers.

и «5.1.3 Удаленный объект и имя объекта Времена жизни»:

Когда буфер, текстуры, пробоотборник, renderbuffer, запроса или синхронизации объект удаляется, его имя сразу становится недействительным (например, отмечен как неиспользуемый), но базовый объект не будет удален до тех пор, пока он больше не будет использоваться.

Буфер, текстура, объект Пробоотборник или renderbuffer находится в использовании, если любое из следующих условий:

объект прикрепляется к любому объекту контейнера

...

ВАО в данном случае считается «контейнерным объектом» для VBO. Таким образом, пока VBO упоминается в VAO, а сам VAO не удаляется, VBO остается в живых. Вот почему ваша версия кода с glDeleteBuffers() в конце работает.

Однако, если VAO в настоящее время связано, и вы удаляете VBO, он автоматически отключается от VAO.Поэтому он больше не ссылается на VAO и немедленно удаляется. Это относится к случаю, когда вы звоните glDeleteBuffers() сразу после glVertexAttribPointer().

В любом случае id (aka name) немедленно становится недействительным. Таким образом, вы не сможете связать его снова и, например, изменить данные.

Есть несколько оговорок, если вы углубитесь в спецификации более глубоко. Например, если вы удаляете буфер, и он остается в живых, поскольку он все еще ссылается на VAO, имя буфера может быть использовано для нового буфера. Это означает, что у вас в основном есть два буфера с тем же именем, что может привести к некоторому запутанному поведению.

Отчасти по этой причине я лично не позволю glDelete*() для объектов, которые вы хотите использовать. Но другим нравится звонить glDelete*() как можно скорее.

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