I am trying to shutdown my DX12 renderer, and restart it within the same process.
Said application is heavily based on the microsoft MiniEngine example code, now with some modification to allow re-initialisation of global variables. I am using SDL for window and event management.
The last stumbling block for a clean shutdown and re-initialisation, it appears, is the loading of textures in a texture manager class, which in turn uses the DirectXTK12
code to load textures, via CreateWICTextureFromFileEx
for .png
files.
To summarise what I'm trying to do:
start up application
initialise rendering into SDL window
render in rendering loop
shut down all rendering and window handling (remove all resources, release device handle) - calls SDL_Quit
re-initialise rendering into new SDL window (get new device handle, etc)
render in rendering loop
The texture management class is shut down as part of the rendering shutdown, removing all traces of textures and their handles to resources etc.
As part of the rendering re-initialisation, the default textures are created via CreateWICTextureFromFileEx
. (see here) and crash when trying to do this.
EDIT: since first posting, I can say that this crashing starts directly after calling SDL_Quit()
(and persists after the call to restart with SDL_Init(SDL_INIT_VIDEO)
)
I am now fairly confident it's an issue with this area specifically rather than some other part of the renderer that isn't being re-initialised correctly, since I can force it to use .DDS
textures instead of .png
s, and the system fires up again nicely. In this case it uses DDSTextureLoader
without any (obvious) problems.
I've added the source to my project and can see the crash is occurring when trying to do this:
ComPtr<IWICBitmapDecoder> decoder;
HRESULT hr = pWIC->CreateDecoderFromFilename(fileName,
nullptr,
GENERIC_READ,
WICDecodeMetadataCacheOnDemand,
decoder.GetAddressOf());
The failure reported is
Unhandled exception thrown: read access violation.
pWIC->**** was 0x7FFAC0B0C610.
pWIC
here is obtained via _GetWIC()
which is using a singleton initialisation:
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;
}
Since first posting, I can now say that this crashing starts directly after calling SDL_Quit()
. I have test code that starts the graphics up enough to get a device and get a texture, which will complete successfully at any point until SDL_Quit
.
Re-initialising SDL with SDL_Init(SDL_INIT_VIDEO)
doesn't help.
I also note that the WICTextureLoader
comments state "Assumes application has already called CoInitializeEx". Is this an area that SDL_Quit
could be messing with?
I'll post an answer here but will remove it if @ChuckWalbourn wants to post his own.
This was due to letting SDL call CoInitialize
for me.
When it cleaned up through SDL_Quit
, it called CoUninitialize
which then (presumably) invalidated the IWICImagingFactory2
set up by WICTextureLoader
.
By adding a call to CoInitialize
in my rendering startup, the internal count in CoInitialize
keeps the IWICImagingFactory2
alive and all is well.