首页 > 解决方案 > 为什么我在关闭 SDL 后无法使用 CreateWICTextureFromFileEx

问题描述

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

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

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

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

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

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

编辑:自从第一次发布以来,我可以说这种崩溃在调用后直接开始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. 重新初始化 SDLSDL_Init(SDL_INIT_VIDEO)并没有帮助。

我还注意到WICTextureLoader评论状态“假设应用程序已经调用了 CoInitializeEx”。这是一个SDL_Quit可以搞砸的领域吗?

标签: c++sdldirectx-12directxtk

解决方案


我会在这里发布一个答案,但如果@ChuckWalbourn 想要发布他自己的答案,我会删除它。

这是因为让 SDL 给CoInitialize我打电话。
当它通过 清理时SDL_Quit,它调用CoUninitializewhich 然后(大概)使IWICImagingFactory2设置无效WICTextureLoader
通过CoInitialize在我的渲染启动中添加一个调用,内部计数CoInitialize保持IWICImagingFactory2活跃,一切都很好。


推荐阅读