gpt4 book ai didi

c++ - std::shared_ptr::reset() "invalidates"其他引用

转载 作者:行者123 更新时间:2023-11-30 03:36:12 26 4
gpt4 key购买 nike

此时我所有的代码都是单线程的。

我有一个纹理管理器,它拥有一个“纹理集合”的集合,这些集合又作为 std::shared_ptr's 持有、“拥有”和管理我的所有游戏纹理。一个集合专门用于我的帧缓冲区纹理。在初始化时,它实例化了我所有的帧缓冲区纹理,随后,一个单独的帧缓冲区对象请求它们并存储它自己的 std::shared_ptr 对这些纹理的引用。我在我的延迟渲染器中使用这个对象。到目前为止没有问题:查看 Visual Studio (2015) 中的调试信息,它显示每个帧缓冲区纹理有两个强引用(一个在集合中,一个在帧缓冲区对象中);正常工作。

问题出现在我的窗口尺寸改变时。我监听 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 保持不变(除了每个纹理的引用计数,它下降到一个)。看来我从根本上误判了 std::shared_ptr 及其 reset() 方法。

我也试过使用间接重新分配,例如:

*_textures["depth"] = PantheraTexture(...)

除了感觉不愉快之外,它不会调用我的纹理对象的析构函数,因此 OpenGL 从不释放无效纹理。

我被难住了。我想让纹理对象本身保持不变,否则我可能会利用 glTexImage*D 为它们实现一个内部调整大小方法。您如何建议在不诉诸于此的情况下保持我的纹理集合和我的帧缓冲区对象之间的连续性?

提前致谢。

最佳答案

一般来说,处理这个问题的方法是停止对不真正拥有对象的事物使用shared_ptr

例如,您有一个 PantheraTextureCollectionFramebuffer,我假设它表示帧缓冲区使用的纹理集合。该对象拥有那些纹理;它管理它们何时被创建、重新创建和销毁。

在其他地方,您可能有一些 Framebuffer 类。现在,它对其使用的纹理具有 shared_ptr,代表对这些纹理的所有权。但它真的拥有那些纹理吗?

不是真的。现在是的,如果您在它们之间共享所有权,那么您可以在仍然使用帧缓冲区的同时销毁集合。但是...您真的想要吗?

没有。从逻辑上讲,如果您销毁了集合,那么使用该集合的帧缓冲区应该被销毁,对吧?但与此同时,也许一个帧缓冲区可以使用来自多个集合的纹理。

在那种情况下,我会说帧缓冲区应该对它从中获取一个或多个图像的任何集合拥有所有权。

此外,这些集合似乎是一组命名图像。因此,用户可能会按名称引用纹理,根据需要从他们的集合中获取实际的纹理对象。

因此,集合需要知道谁拥有它们,以便在更新或修改纹理时,可以通知它们。至少,这个帧缓冲区集合类需要在更新纹理时通知任何引用它的帧缓冲区,以便它们可以重新初始化所需的任何数据。

which, aside from feeling unpleasantly hacky, doesn't call my texture objects' destructors and so OpenGL never frees the invalid textures.

那么您一定没有在您的字体中正确使用三/五法则。您允许它可复制,但您没有正确实现复制行为。

你应该让你的类型不可复制,因为为纹理包装器实现正确的复制行为不是一个好主意。

关于c++ - std::shared_ptr::reset() "invalidates"其他引用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40813847/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com