diff --git a/Apps/UnitTests/Source/Tests.Device.D3D11.cpp b/Apps/UnitTests/Source/Tests.Device.D3D11.cpp index 4168cbdaa..ae573e6b4 100644 --- a/Apps/UnitTests/Source/Tests.Device.D3D11.cpp +++ b/Apps/UnitTests/Source/Tests.Device.D3D11.cpp @@ -6,6 +6,8 @@ #include +extern Babylon::Graphics::Configuration g_deviceConfig; + namespace { winrt::com_ptr CreateDevice() @@ -101,3 +103,26 @@ TEST(Device, BackBuffer) device.FinishRenderingCurrentFrame(); } } + +// Verifies that UpdateDevice throws when called while rendering is enabled. +TEST(Device, UpdateDeviceThrowsWhenRenderingEnabled) +{ + winrt::com_ptr d3dDevice = CreateDevice(); + + Babylon::Graphics::Configuration config = g_deviceConfig; + config.Device = d3dDevice.get(); + + Babylon::Graphics::Device device{config}; + + // Permitted before EnableRendering. + EXPECT_NO_THROW(device.UpdateDevice(d3dDevice.get())); + + // StartRenderingCurrentFrame triggers EnableRendering -> throws. + device.StartRenderingCurrentFrame(); + EXPECT_THROW(device.UpdateDevice(d3dDevice.get()), std::runtime_error); + device.FinishRenderingCurrentFrame(); + + // Permitted again after DisableRendering. + device.DisableRendering(); + EXPECT_NO_THROW(device.UpdateDevice(d3dDevice.get())); +} diff --git a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h index 8a529cdee..6374161d3 100644 --- a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h +++ b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h @@ -112,7 +112,15 @@ namespace Babylon::Graphics // method and structure might change. void UpdateWindow(WindowT window); + + // Sets the underlying graphics device used for rendering. The new device takes effect on + // the next EnableRendering call. + // + // Only valid when rendering is disabled -- i.e. before the first EnableRendering / + // StartRenderingCurrentFrame call, or after a DisableRendering call. Throws + // std::runtime_error otherwise. void UpdateDevice(DeviceT device); + void UpdateSize(size_t width, size_t height); void UpdateMSAA(uint8_t value); void UpdateAlphaPremultiplied(bool enabled); diff --git a/Core/Graphics/Source/DeviceImpl.cpp b/Core/Graphics/Source/DeviceImpl.cpp index 93a3fa75e..30b9b01b1 100644 --- a/Core/Graphics/Source/DeviceImpl.cpp +++ b/Core/Graphics/Source/DeviceImpl.cpp @@ -108,6 +108,10 @@ namespace Babylon::Graphics void DeviceImpl::UpdateDevice(DeviceT device) { std::scoped_lock lock{m_state.Mutex}; + if (m_state.Bgfx.Initialized) + { + throw std::runtime_error{"UpdateDevice called while rendering is enabled."}; + } m_state.Bgfx.InitState.platformData.context = device; m_state.Bgfx.Dirty = true; }