为什么我在关闭 SDL 后无法使用 CreateWICTextureFromFileEx
Why am I unable to use CreateWICTextureFromFileEx after shutting down SDL
我正在尝试关闭我的 DX12 渲染器,然后在同一进程中重新启动它。
所述应用程序主要基于 Microsoft MiniEngine 示例代码,现在进行了一些修改以允许重新初始化全局变量。我将 SDL 用于 window 和事件管理。
干净关闭和重新初始化的最后一个绊脚石似乎是在纹理管理器 class 中加载纹理,后者又使用 DirectXTK12
代码加载纹理,通过 CreateWICTextureFromFileEx
获取 .png
个文件。
总结一下我正在尝试做的事情:
启动应用程序
将渲染初始化为 SDL window
在渲染循环中渲染
关闭所有渲染和window处理(删除所有资源,释放设备句柄)-调用SDL_Quit
将渲染重新初始化为新的 SDL window(获取新的设备句柄等)
在渲染循环中渲染
纹理管理 class 作为渲染关闭的一部分被关闭,删除所有纹理痕迹及其资源句柄等。
作为渲染重新初始化的一部分,默认纹理是通过 CreateWICTextureFromFileEx
创建的。 (参见 here)并在尝试执行此操作时崩溃。
编辑:自第一次发布以来,我可以说这种崩溃是在调用 SDL_Quit()
后直接开始的(并在调用 SDL_Init(SDL_INIT_VIDEO)
重新启动后持续存在)
我现在相当有信心这是这个区域的问题,而不是渲染器的其他部分没有正确重新初始化,因为我可以强制它使用 .DDS
纹理而不是.png
s,系统再次正常启动。在这种情况下,它使用 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
评论指出“假设应用程序已经调用了 CoInitializeEx”。这是 SDL_Quit
可能搞砸的区域吗?
我会 post 在这里回答,但如果@ChuckWalbourn 想要 post 他自己的答案,我会删除它。
这是因为让 SDL 为我调用 CoInitialize
。
当它通过 SDL_Quit
清理时,它调用 CoUninitialize
然后(大概)使 WICTextureLoader
设置的 IWICImagingFactory2
无效。
在我的渲染启动中添加对 CoInitialize
的调用,CoInitialize
中的内部计数使 IWICImagingFactory2
保持活动状态并且一切正常。
我正在尝试关闭我的 DX12 渲染器,然后在同一进程中重新启动它。
所述应用程序主要基于 Microsoft MiniEngine 示例代码,现在进行了一些修改以允许重新初始化全局变量。我将 SDL 用于 window 和事件管理。
干净关闭和重新初始化的最后一个绊脚石似乎是在纹理管理器 class 中加载纹理,后者又使用 DirectXTK12
代码加载纹理,通过 CreateWICTextureFromFileEx
获取 .png
个文件。
总结一下我正在尝试做的事情:
启动应用程序
将渲染初始化为 SDL window
在渲染循环中渲染
关闭所有渲染和window处理(删除所有资源,释放设备句柄)-调用
SDL_Quit
将渲染重新初始化为新的 SDL window(获取新的设备句柄等)
在渲染循环中渲染
纹理管理 class 作为渲染关闭的一部分被关闭,删除所有纹理痕迹及其资源句柄等。
作为渲染重新初始化的一部分,默认纹理是通过 CreateWICTextureFromFileEx
创建的。 (参见 here)并在尝试执行此操作时崩溃。
编辑:自第一次发布以来,我可以说这种崩溃是在调用 SDL_Quit()
后直接开始的(并在调用 SDL_Init(SDL_INIT_VIDEO)
重新启动后持续存在)
我现在相当有信心这是这个区域的问题,而不是渲染器的其他部分没有正确重新初始化,因为我可以强制它使用 .DDS
纹理而不是.png
s,系统再次正常启动。在这种情况下,它使用 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
评论指出“假设应用程序已经调用了 CoInitializeEx”。这是 SDL_Quit
可能搞砸的区域吗?
我会 post 在这里回答,但如果@ChuckWalbourn 想要 post 他自己的答案,我会删除它。
这是因为让 SDL 为我调用 CoInitialize
。
当它通过 SDL_Quit
清理时,它调用 CoUninitialize
然后(大概)使 WICTextureLoader
设置的 IWICImagingFactory2
无效。
在我的渲染启动中添加对 CoInitialize
的调用,CoInitialize
中的内部计数使 IWICImagingFactory2
保持活动状态并且一切正常。