1. ホーム
  2. opengl

[解決済み] glDeleteBuffers()はいつ呼び出すべきですか?

2022-02-19 08:54:56

質問

以下のようなコードがありますが、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);

現在、VAOのバインドを解除した後、そのままglDeleteBuffersを呼び出しています。私は、マークされた別の位置でそれを呼び出すことを試みました - 私が属性ポインタを設定した直後。私の推測では、これは、私が描画の呼び出しを行ったとき、私がそれを削除したので、描画されるデータがなかったからだと思います。

困惑しているのは、現在私が持っているように動作することです。私は、a) バッファが削除されたときに何が起こるかをよく理解していない、b) 偶然にしか動作せず、予期せず破損する可能性がある、と心配しています。

私が理解する限り、glDeleteBuffers を呼び出すとデータが削除されるので、描画するデータはないはずです - しかし、あります。そのため、私の他の考えは、VAOを再バインドしたときにデータが復元されることでした。しかし、データがどこから復元されるのか理由が分からないため、私にはあまり意味がありませんでした。

どなたか、glDeleteBufferの使い方が正しいかどうか、正しくなければどこで呼び出すべきか(これ以上データを描画する必要がなくなった時点、おそらくプログラムの終了時だと思います)、教えていただけませんか?

どのように解決するのですか?

あなたが見ているものは、よく定義された動作です。以下は、これに関連する仕様の重要な部分です(強調)。

OpenGL 4.5仕様の「5.1.2 Automatic Unbinding of Deleted Objects"」セクションからです。

バッファ、テクスチャ、レンダーバッファのオブジェクトが削除されると、それは 現在のコンテキストでバインドされているすべてのバインドポイントからバインドを解除します。 そして 現在のコンテキストにバインドされているコンテナオブジェクトのアタッチメントから切り離される。 DeleteBuffers、DeleteTextures、および DeleteRenderbuffers で説明したとおりです。

および "5.1.3 Deleted Object and Object Name Lifetimes" を参照してください。

バッファ、テクスチャ、サンプラ、レンダーバッファ、クエリ、または同期オブジェクトが削除されたとき、その という名前はすぐに無効になってしまいます。 (例: 未使用とマークされる)、しかし の下にあるオブジェクトは、それが使用されなくなるまで削除されません。 .

バッファ、テクスチャ、サンプラー、レンダーバッファオブジェクトは、以下の条件のいずれかを満たす場合に使用中となります。

オブジェクトがいずれかのコンテナ・オブジェクトにアタッチされている

...

この場合、VAOはVBOの"コンテナ・オブジェクト"とみなされます。つまり、VBOがVAOから参照されている限り、そしてVAO自体が削除されない限り、VBOは生き続けるのです。このため、あなたのバージョンのコードで glDeleteBuffers() を最後につけるとうまくいきます。

ただし、現在VAOにバインドされている状態で、VBOを削除すると、VAOから自動的にバインドが解除されます。したがって、VAOから参照されなくなり、すぐに削除されます。これは glDeleteBuffers() の直後に glVertexAttribPointer() .

いずれにせよ、id(別名:名前)は即座に無効となる。そのため、再度バインドしてデータを変更することなどはできません。

もっと仕様を掘り下げると、いくつか注意点があります。例えば、あるバッファを削除しても、VAOから参照されているため、そのバッファが生き続ける場合、そのバッファの名前を新しいバッファに使用することができます。これは、基本的に同じ名前の2つのバッファを持つことを意味し、いくつかの混乱した動作になる可能性があります。

そのような理由もあり、個人的には glDelete*() は、使い続けたいオブジェクトのためのものです。しかし、他の人は glDelete*() をなるべく早く実行します。