【问题标题】:Why am I unable to use CreateWICTextureFromFileEx after shutting down SDL为什么我在关闭 SDL 后无法使用 CreateWICTextureFromFileEx
【发布时间】:2021-11-15 15:08:30
【问题描述】:

我正在尝试关闭我的 DX12 渲染器,然后在同一进程中重新启动它。

所述应用程序很大程度上基于 microsoft MiniEngine 示例代码,现在进行了一些修改以允许重新初始化全局变量。我正在使用 SDL 进行窗口和事件管理。

看来,彻底关闭和重新初始化的最后一个绊脚石是在纹理管理器类中加载纹理,该类又使用DirectXTK12 代码加载纹理,通过CreateWICTextureFromFileEx 为@987654324 @ 文件。

总结一下我正在尝试做的事情:

  • 启动应用程序

  • 初始化渲染到 SDL 窗口

  • 在渲染循环中渲染

  • 关闭所有渲染和窗口处理(移除所有资源,释放设备句柄)-调用SDL_Quit

  • 重新初始化渲染到新的 SDL 窗口(获取新的设备句柄等)

  • 在渲染循环中渲染

纹理管理类作为渲染关闭的一部分被关闭,移除所有纹理痕迹及其对资源的句柄等。

作为渲染重新初始化的一部分,默认纹理是通过CreateWICTextureFromFileEx 创建的。 (请参阅here)并在尝试执行此操作时崩溃。

编辑:自从第一次发帖以来,我可以说这个崩溃是在调用SDL_Quit() 之后直接开始的(并且在调用SDL_Init(SDL_INIT_VIDEO) 重启之后仍然存在)

我现在相当有信心这是这个区域的问题,而不是渲染器的其他部分没有正确重新初始化,因为我可以强制它使用.DDS纹理而不是.pngs ,并且系统再次很好地启动。在这种情况下,它使用DDSTextureLoader 没有任何(明显的)问题。

我已将源代码添加到我的项目中,并且在尝试执行此操作时可以看到正在发生崩溃:

ComPtr<IWICBitmapDecoder> decoder;
    HRESULT hr = pWIC->CreateDecoderFromFilename(fileName,
        nullptr,
        GENERIC_READ,
        WICDecodeMetadataCacheOnDemand,
        decoder.GetAddressOf());

报告的失败是

Unhandled exception thrown: read access violation.
pWIC->**** was 0x7FFAC0B0C610.

pWIC 这里是通过 _GetWIC() 获得的,它使用单例初始化:

IWICImagingFactory2* _GetWIC() noexcept
    {
        static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;

        IWICImagingFactory2* factory = nullptr;
        if (!InitOnceExecuteOnce(
            &s_initOnce,
            InitializeWICFactory,
            nullptr,
            reinterpret_cast<LPVOID*>(&factory)))
        {
            return nullptr;
        }

        return factory;
    }

自从第一次发帖以来,我现在可以说这个崩溃是在调用SDL_Quit() 之后直接开始的。我有测试代码可以启动图形以获取设备并获取纹理,这将在任何时候成功完成,直到SDL_Quit。 使用 SDL_Init(SDL_INIT_VIDEO) 重新初始化 SDL 没有帮助。

我还注意到WICTextureLoader cmets 状态“假设应用程序已调用 CoInitializeEx”。这是SDL_Quit 可能搞砸的领域吗?

【问题讨论】:

  • 疯狂猜测,但 afaik,WICTextureLoader 需要在使用前调用 CoInitialize。也许SDL_Quit 打电话给CoUninitialize
  • 确实如此 - 除了 SDL_Init 之外,我必须调用其他东西才能让它再次调用 CoInitialize
  • 我不确定在_GetWIC 中初始化的工厂在CoUninitialize 之后是否仍然有效?
  • CoInitialize 有一个内部计数,请尝试在启动时多次调用它,看看是否有区别。
  • 这就像@ChuckWalbourn 的魅力,谢谢!

标签: c++ sdl directx-12 directxtk


【解决方案1】:

我将在此处发布答案,但如果 @ChuckWalbourn 想要发布他自己的答案,我会将其删除。

这是因为让 SDL 为我致电 CoInitialize
当它通过SDL_Quit 进行清理时,它调用了CoUninitialize,然后(可能)使WICTextureLoader 设置的IWICImagingFactory2 无效。
通过在我的渲染启动中添加对CoInitialize 的调用, CoInitialize 中的内部计数使 IWICImagingFactory2 保持活跃,一切都很好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 2021-12-27
    • 1970-01-01
    • 2023-03-09
    • 2014-08-07
    • 2020-01-29
    • 2013-08-11
    相关资源
    最近更新 更多