Support device loss in NativeEngine implementation
Support things like:
- [ ] Graphics device is changed
- [ ] Remote desktop
This seems to be mostly desktop scenarios.
First step is to investigate whether this is a problem or not.
Device loss in Office
The way Office currently handles device loss is by providing a new D3D11Device in the Renderer constructor, or switching from the constructor that receives a D3D11Device to the that only received the dimensions of the render target texture (used when the graphics device is a Sofware renderer). It does not seem to be a API that gets called to specifically signal to Spectre that the graphics device has been lost.
The way base3D handles it is by using whatever device is provided by Office for the rendering (including switching devices when going in preset mode). Base3D holds a list o devices and it basically duplicates all GPU resources across all provided devices.
Babylon Native handles it differently, we receive a device during factory initialization and use that device all the time. When the factory device does not match what is provided by the renderer constructor we just create a own render target a do a GPU copy (or CPU when it is not possible to do the copy in the GPU). This works fine for preset mode, but it is not enough for device loss.
Babylon Native device loss in Office
The correct way to handle device loss in Office using Babylon Native would be to try to create the D3D11Texture using the factory device and check the returned HRESULT. If the HRESULT fails we should check ID3D11Device::GetDeviceRemovedReason, if it returns anything different than S_OK we know we are in a device loss scenario.
The factory must call Babylon::Graphics::Device::DisableRendering followed by Babylon::Graphics::Device::UpdateDevice giving the new device provided in the Renderer's constructor, and finally it should call Babylon::Device::EnableRendering. This will make Babylon.js re-load all GPU resources from the scene into the new graphics device.
Problems with the current approach
The main problem with this approach is that bgfx has a special behavior when calling Babylon::Graphics::Device::DisableRendering, since there is no render target attached bgfx will try to create a new one using the current device it has. This will cause issues since the device is no longer valid.
For solving this problem we have a couple of possibilities:
1 - Change bgfx to properly check HRESULTS from the graphics call (currently it only checks them in debug and asserts). If a HRESULT indicates that the device has been lost bgfx should no longer make call to that device.
2 - Figure out a way for bgfx to not try to create a render target during shutdown.