此时我的所有代码都是单线程的。
我有一个纹理管理器,拥有一组"纹理集合"反过来持有,"拥有"并将我的所有游戏纹理管理为std::shared_ptr's
。一个集合专门用于我的帧缓冲纹理。在初始化时,它实例化我的所有帧缓冲区纹理,之后,一个单独的帧缓冲区对象请求它们全部并存储它自己的std::shared_ptr
对这些纹理的引用。我在延迟渲染器中使用此对象。到目前为止没问题:查看Visual Studio(2015)中的调试信息,它显示了每个帧缓冲纹理的两个强引用(集合中的一个,以及framebuffer对象中的一个);按计划工作。
当窗口尺寸发生变化时,问题就出现了。我在监听WM_SIZE
事件,调整大小后,我的WndProc调用以下内容(再次,在我的帧缓冲纹理集合中的引用,而不是我的帧缓冲对象 - 遵守我的所有权约定):
void PantheraTextureCollectionFramebuffer::Resize( unsigned int width, unsigned int height ) {
_textures["depth"].reset( new PantheraTexture( width, height, PantheraTextureFormat::Depth24,
PantheraTextureMinFilter::Nearest, PantheraTextureMagFilter::Nearest ) );
_textures["diffuseSpecular"].reset( new PantheraTexture( width, height, PantheraTextureFormat::RGBA8,
PantheraTextureMinFilter::Nearest, PantheraTextureMagFilter::Nearest ) );
_textures["normalParallax"].reset( new PantheraTexture( width, height, PantheraTextureFormat::RGBA8,
PantheraTextureMinFilter::Nearest, PantheraTextureMagFilter::Nearest ) );
_textures["position"].reset( new PantheraTexture( width, height, PantheraTextureFormat::RGB16F,
PantheraTextureMinFilter::Nearest, PantheraTextureMagFilter::Nearest ) );
_textures["uvMaterial"].reset( new PantheraTexture( width, height, PantheraTextureFormat::RGB16F,
PantheraTextureMinFilter::Nearest, PantheraTextureMagFilter::Nearest ) );
}
使用新窗口尺寸重新创建所有纹理。 但是,帧缓冲对象中的std::shared_ptr's
保持不变(除了每个纹理的引用计数,它们降为1)。我似乎从根本上误判了std::shared_ptr
及其reset()
方法。
我也尝试过使用间接重新分配,例如:
*_textures["depth"] = PantheraTexture(...)
除了感觉不愉快的hacky之外,没有调用我的纹理对象'析构函数,因此OpenGL永远不会释放无效的纹理。
我很难过。我想保持纹理对象本身不变,否则我可能会为它们实现一个内部的Resize方法,利用glTexImage * D.您如何建议我在保持纹理集合和帧缓冲对象之间的连续性而不诉诸于此?
提前致谢。
答案 0 :(得分:2)
通常,处理此问题的方法是让您停止使用shared_ptr
来处理那些并非真正拥有对象的内容。
例如,你有一个PantheraTextureCollectionFramebuffer
,我假设它代表了一个由帧缓冲区使用的纹理集合。这个对象拥有那些纹理;它管理它们何时被创建,重新创建和销毁。
在其他地方,你可能会有一些Framebuffer
课程。现在,它对它使用的纹理有shared_ptr
个,表示对这些纹理的所有权。但真的拥有这些纹理吗?
不是真的。现在是的,如果你在它们之间共享所有权,那么你可以在使用帧缓冲区时销毁该集合。但是......你真的想要吗?
没有。从逻辑上讲,如果你销毁了这个集合,那么使用该集合的framebuffer 也也会被销毁,对吗?但与此同时,也许帧缓冲可以使用来自多个集合的纹理。
在这种情况下,我会说帧缓冲应声明对其获取一个或多个图像的任何集合的所有权。
此外,这些集合似乎是一组命名图像。因此,用户可能会按名称引用纹理,根据需要从其集合中获取实际纹理对象。
因此,集合需要知道谁拥有它们,以便在更新或修改纹理时,可以通知它们。至少,这个帧缓冲集合类需要告诉任何在更新纹理时引用它的帧缓冲区,以便它们可以重新初始化它们所需的任何数据。
除了感觉不愉快的hacky之外,不会调用我的纹理对象的析构函数,因此OpenGL永远不会释放无效的纹理。
然后你不能在你的类型中正确使用三/五规则。您允许它是可复制的,但您没有正确实现复制行为。
您应该使您的类型不可复制,因为为纹理包装器实现正确的复制行为不是一个好主意。