OpenGL新纹理在删除后取代旧纹理
OpenGL new textures replacing old ones after deletion
我遇到了一些令人困惑的问题与OpenGL,它是相当简单,但我没能找到任何直接相关的信息。
我想做什么
我每帧创建几个新的纹理,创建后立即绑定它们,使用它们进行绘制,然后删除它们。
问题如果我在使用后立即删除每个纹理,那么最后一个要绘制的纹理将替换之前的纹理(但它们的不同几何形状应该如此)。如果我在所有绘制完成后批量删除,它会像预期的那样工作,但如果我在删除纹理后进行任何绘制调用,则最后一次绘制调用中使用的纹理会替换旧的纹理(可能是一些常见的永久精灵纹理)。
调试结果
我尝试过使用glFlush(),它似乎根本没有做任何事情,根本没有删除纹理给出正确的行为,也没有在删除纹理和调用SwapBuffers()作品之间绘制任何东西。
代码这不是我的代码看起来像什么,但这是相关部分归结为:
int Tex1, Tex2, Tex3;
glGenTextures(1, &Tex1);
glBindTexture(GL_TEXTURE_2D, Tex1);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex1
glGenTextures(1, &Tex2);
glBindTexture(GL_TEXTURE_2D, Tex2);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex2
// I delete some textures here.
glDeleteTextures(1, &Tex1);
glDeleteTextures(1, &Tex2);
// If I comment out this section, everything works correctly
// If I leave it in, this texture replaces Tex1 and Tex2, but
// the geometry is correct for each geometry batch.
glGenTextures(1, &Tex3);
glBindTexture(GL_TEXTURE_2D, Tex3);
// ... Fill Texture with data, set correct filtering etc.
glDrawElements(GL_TRIANGLES, ...); // Using Tex3
glDeleteTextures(1, &Tex3);
// ...
SwapBuffers();
我怀疑这可能与OpenGL缓冲我的draw调用有关,当它们真正被处理的时候,纹理被删除了吗?这对我来说并没有什么意义,为什么在删除之前的纹理后绘制其他会导致这种行为?
更多上下文生成的纹理是文本字符串,可能会或可能不会改变每帧,现在我为每个字符串每帧创建新的纹理,然后渲染纹理并在之后丢弃它。位图数据由Windows GDI生成。
我不是真的在寻找效率方面的建议,理想情况下我想要一个答案,可以引用使用这样的临时纹理渲染的预期/正确行为的文档,以及这种方法可能存在的常见问题。
预期的行为是明确的。您可以在使用完对象后立即删除它们。在你的情况下,在你使用纹理进行绘制调用之后,你可以在这些纹理上调用glDeleteTextures()
。你方不需要采取额外的预防措施。
我在OpenGL 4.5规范的第28页找到了最清晰的表达:
如果一个对象在当前被GL上下文使用时被删除,它的名称立即被标记为未使用,并且某些类型的对象会自动从当前上下文的绑定点解除绑定,如5.1.2节所述。但是,实际的底层对象直到不再使用时才会被删除。
在你的代码中,这意味着驱动程序不能删除纹理,直到GPU完成使用纹理的绘制调用。
为什么这在你的情况下不起作用很难说。有一种可能性是,代码中的某些内容总是无意中提前删除了纹理。对于复杂的软件架构,这比您想象的要容易得多。例如,一个非常流行的原因是人们将OpenGL对象包装在c++类中,并让这些c++对象超出作用域,而底层OpenGL对象仍在使用中。
所以你绝对应该仔细检查(例如通过使用调试断点或日志记录),删除纹理的代码不会在意外的时间被调用。
另一个选项是驱动程序错误。虽然对象生命周期管理并非完全无关紧要,但它是如此重要,以至于很难想象它在非常基本的情况下会被破坏。但这当然是可能的,或多或少取决于供应商和平台。
作为一个解决方案,你可以尝试不删除纹理对象,而只指定新的数据(使用glTexImage2D()
)为相同的对象。如果纹理大小不变,用glTexSubImage2D()
替换数据可能会更有效。
- 将数组的地址分配给变量并删除
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- C/C++编译器通常会删除重复的库吗
- 从链接列表c++中删除一个项目
- C++如何通过用户输入删除列表元素
- 为什么在C++中使用私有复制构造函数与删除复制构造函数
- OpenInventor从9.8升级到10.4.2后,GLSL纹理返回零
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 使用函数"remove"删除重复元素
- 如何从多映射中删除特定的重复项
- 运算符C++ "delete []"仅删除 2 个前值
- 删除指向指针的指针是运行时错误吗
- 将指针设置为"nullptr"并不能防止双重删除?
- SFML 纹理持有人已删除,但仍在范围内
- OpenGL新纹理在删除后取代旧纹理
- 如何删除一次制作的所有纹理
- 在opengl中删除未使用的纹理
- 从记忆中找到和删除隐藏纹理的最佳方法