Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
ba00c29
Reworked threading model.
bkaradzic Mar 25, 2026
31dbf03
Added first frame started check.
bkaradzic Apr 6, 2026
446754e
Fixed ordering.
bkaradzic Apr 8, 2026
f279a95
Capture just POD values.
bkaradzic Apr 8, 2026
e917d8f
Removed unused captures.
bkaradzic Apr 8, 2026
0a1f98e
Fix null encoder crash in Canvas::Flush by adding defensive check aft…
bkaradzic Apr 8, 2026
0d315bb
Fix LoadCubeTexture*.
bkaradzic Mar 12, 2026
4528d1e
Fix null encoder crash in SubmitCommands by using stack-scoped FrameC…
bkaradzic Apr 8, 2026
bed4ed2
Always acquire FrameCompletionScope in SubmitCommands to prevent enco…
bkaradzic Apr 8, 2026
d7c78cb
Revert "Fix LoadCubeTexture*."
bkaradzic Apr 8, 2026
c1d777c
Fix LocaCubeTexture*.
bkaradzic Apr 8, 2026
8ebdeee
Pump frames in JavaScript unit test to prevent deadlock from always-a…
bkaradzic Apr 8, 2026
dac7eff
Fix unit test shutdown race by using 16ms frame interval instead of s…
bkaradzic Apr 8, 2026
170b841
Keep frame open during unit test shutdown to prevent JS thread deadlo…
bkaradzic Apr 9, 2026
3139f59
Fix PrecompiledShaderTest deadlock by keeping frame open during start…
bkaradzic Apr 9, 2026
df6c638
Revert ReadTexture to inline blit with FrameCompletionScope — BeforeR…
bkaradzic Apr 9, 2026
586356f
Discard encoder state before Canvas Flush to prevent NativeEngine sta…
bkaradzic Apr 9, 2026
9f25ed5
Add FrameCompletionScope to ReadTexture — called during init and from…
bkaradzic Apr 9, 2026
758fcdc
Removed DeviceUpdate.
bkaradzic Apr 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Apps/HeadlessScreenshotApp/Win32/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,10 @@ int main()

// Create the Babylon Native graphics device and update.
auto device = CreateGraphicsDevice(d3dDevice.get());
auto deviceUpdate = device.GetUpdate("update");

// Start rendering a frame to unblock the JavaScript from queuing graphics
// commands.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();

// Create a Babylon Native application runtime which hosts a JavaScript
// engine on a new thread.
Expand Down Expand Up @@ -156,12 +154,17 @@ int main()
addToContext.get_future().wait();

// Render a frame so that `AddToContextAsync` will complete.
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

// Reopen the gate so JS can continue running (startup may issue bgfx commands).
device.StartRenderingCurrentFrame();

// Wait for `startup` to finish.
startup.get_future().wait();

// Close the frame opened above.
device.FinishRenderingCurrentFrame();

struct Asset
{
const char* Name;
Expand All @@ -181,7 +184,6 @@ int main()

// Start rendering a frame to unblock the JavaScript again.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();

std::promise<void> loadAndRenderAsset{};

Expand All @@ -204,7 +206,6 @@ int main()
loadAndRenderAsset.get_future().wait();

// Finish rendering the frame.
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

// Tell RenderDoc to stop capturing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -167,10 +167,8 @@ extern "C"
{
if (appContext)
{
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();
appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}

Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/Shared/AppContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,10 @@ AppContext::AppContext(
graphicsConfig.MSAASamples = 4;

m_device.emplace(graphicsConfig);
m_deviceUpdate.emplace(m_device->GetUpdate("update"));

Babylon::Plugins::ShaderCache::Enable();

m_device->StartRenderingCurrentFrame();
m_deviceUpdate->Start();

Babylon::AppRuntime::Options options{};

Expand Down Expand Up @@ -143,7 +141,6 @@ AppContext::~AppContext()
{
if (m_device)
{
m_deviceUpdate->Finish();
m_device->FinishRenderingCurrentFrame();
}

Expand All @@ -153,6 +150,5 @@ AppContext::~AppContext()
m_canvas.reset();
m_input = {};
m_runtime.reset();
m_deviceUpdate.reset();
m_device.reset();
}
2 changes: 0 additions & 2 deletions Apps/Playground/Shared/AppContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,13 @@ class AppContext
AppContext& operator=(AppContext&&) noexcept = delete;

Babylon::Graphics::Device& Device() { return *m_device; }
Babylon::Graphics::DeviceUpdate& DeviceUpdate() { return *m_deviceUpdate; }
Babylon::AppRuntime& Runtime() { return *m_runtime; }
Babylon::Polyfills::Canvas& Canvas() { return *m_canvas; }
Babylon::Plugins::NativeInput* Input() { return m_input; }
Babylon::ScriptLoader& ScriptLoader() { return *m_scriptLoader; }

private:
std::optional<Babylon::Graphics::Device> m_device;
std::optional<Babylon::Graphics::DeviceUpdate> m_deviceUpdate;
std::optional<Babylon::AppRuntime> m_runtime;
std::optional<Babylon::Polyfills::Canvas> m_canvas;
Babylon::Plugins::NativeInput* m_input{};
Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/UWP/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -109,10 +109,8 @@ void App::Run()
{
if (m_appContext)
{
m_appContext->DeviceUpdate().Finish();
m_appContext->Device().FinishRenderingCurrentFrame();
m_appContext->Device().StartRenderingCurrentFrame();
m_appContext->DeviceUpdate().Start();
}

CoreWindow::GetForCurrentThread().Dispatcher().ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
Expand Down Expand Up @@ -156,7 +154,6 @@ void App::OnSuspending(IInspectable const& /*sender*/, SuspendingEventArgs const

if (m_appContext)
{
m_appContext->DeviceUpdate().Finish();
m_appContext->Device().FinishRenderingCurrentFrame();

m_appContext->Runtime().Suspend();
Expand All @@ -175,7 +172,6 @@ void App::OnResuming(IInspectable const& /*sender*/, IInspectable const& /*args*
m_appContext->Runtime().Resume();

m_appContext->Device().StartRenderingCurrentFrame();
m_appContext->DeviceUpdate().Start();
}
}

Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/Win32/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,10 +155,8 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
{
if (appContext)
{
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();
appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}

result = PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) && msg.message != WM_QUIT;
Expand Down Expand Up @@ -279,7 +277,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (appContext)
{
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();

appContext->Runtime().Suspend();
Expand All @@ -298,7 +295,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
appContext->Runtime().Resume();

appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}
}
Expand Down
2 changes: 0 additions & 2 deletions Apps/Playground/X11/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -136,10 +136,8 @@ int main(int _argc, const char* const* _argv)
{
if (!XPending(display) && g_appContext)
{
g_appContext->DeviceUpdate().Finish();
g_appContext->Device().FinishRenderingCurrentFrame();
g_appContext->Device().StartRenderingCurrentFrame();
g_appContext->DeviceUpdate().Start();
}
else
{
Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/iOS/LibNativeBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,20 @@ - (void)resize:(int)inWidth height:(int)inHeight
{
if (appContext)
{
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();

appContext->Device().UpdateSize(static_cast<size_t>(inWidth), static_cast<size_t>(inHeight));

appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}

- (void)render
{
if (appContext)
{
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();
appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}

Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/macOS/ViewController.mm
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,19 @@ @implementation EngineView
- (void)mtkView:(MTKView *)__unused view drawableSizeWillChange:(CGSize) size
{
if (appContext) {
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();

appContext->Device().UpdateSize(static_cast<size_t>(size.width), static_cast<size_t>(size.height));

appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}

- (void)drawInMTKView:(MTKView *)__unused view
{
if (appContext) {
appContext->DeviceUpdate().Finish();
appContext->Device().FinishRenderingCurrentFrame();
appContext->Device().StartRenderingCurrentFrame();
appContext->DeviceUpdate().Start();
}
}

Expand Down
4 changes: 0 additions & 4 deletions Apps/Playground/visionOS/LibNativeBridge.mm
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,11 @@ - (bool)initializeWithWidth:(NSInteger)width height:(NSInteger)height {

- (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height {
if (_appContext) {
_appContext->DeviceUpdate().Finish();
_appContext->Device().FinishRenderingCurrentFrame();

_appContext->Device().UpdateSize(static_cast<size_t>(width), static_cast<size_t>(height));

_appContext->Device().StartRenderingCurrentFrame();
_appContext->DeviceUpdate().Start();
}
}

Expand All @@ -67,10 +65,8 @@ - (void)setTouchUp:(int)pointerId x:(int)inX y:(int)inY {

- (void)render {
if (_appContext && self.initialized) {
_appContext->DeviceUpdate().Finish();
_appContext->Device().FinishRenderingCurrentFrame();
_appContext->Device().StartRenderingCurrentFrame();
_appContext->DeviceUpdate().Start();
}
}

Expand Down
11 changes: 6 additions & 5 deletions Apps/PrecompiledShaderTest/Source/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,12 +103,10 @@ int RunApp(

// Create the Babylon Native graphics device and update.
auto device = Babylon::Graphics::Device(config);
auto deviceUpdate = device.GetUpdate("update");

// Start rendering a frame to unblock the JavaScript from queuing graphics
// commands.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();

// Create a Babylon Native application runtime which hosts a JavaScript
// engine on a new thread.
Expand Down Expand Up @@ -163,15 +161,19 @@ int RunApp(
addToContext.get_future().wait();

// Render a frame so that `AddToContextAsync` will complete.
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

// Reopen the gate so JS can continue running (startup may issue bgfx commands).
device.StartRenderingCurrentFrame();

// Wait for `startup` to finish.
startup.get_future().wait();

// Close the frame opened above.
device.FinishRenderingCurrentFrame();

// Start a new frame for rendering the scene.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();

std::promise<void> renderScene{};

Expand All @@ -193,7 +195,6 @@ int RunApp(
renderScene.get_future().wait();

// Finish the frame.
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

// Save the rendered output as a PNG.
Expand Down
17 changes: 6 additions & 11 deletions Apps/StyleTransferApp/Win32/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@ namespace
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name

std::optional<Babylon::Graphics::Device> g_device{};
std::optional<Babylon::Graphics::DeviceUpdate> g_update{};
Babylon::Plugins::NativeInput* g_nativeInput{};
std::optional<Babylon::AppRuntime> g_runtime{};
bool g_minimized{false};
Expand Down Expand Up @@ -219,13 +218,11 @@ namespace
{
if (g_device)
{
g_update->Finish();
g_device->FinishRenderingCurrentFrame();
}

g_nativeInput = {};
g_runtime.reset();
g_update.reset();
g_device.reset();
}

Expand Down Expand Up @@ -300,12 +297,10 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
// --------------------- Babylon Native initialization --------------------------

g_device = CreateBabylonGraphicsDevice(d3d11Device.get());
g_update.emplace(g_device->GetUpdate("update"));

// Start rendering a frame to unblock the JavaScript from queuing graphics
// commands.
g_device->StartRenderingCurrentFrame();
g_update->Start();

// Create a Babylon Native application runtime which hosts a JavaScript
// engine on a new thread.
Expand Down Expand Up @@ -359,20 +354,24 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
addToContext.get_future().wait();

// Render a frame so that `AddToContextAsync` will complete.
g_update->Finish();
g_device->FinishRenderingCurrentFrame();

// Reopen the gate so JS can continue running (startup may issue bgfx commands).
g_device->StartRenderingCurrentFrame();

// Wait for `startup` to finish.
startup.get_future().wait();

// Close the frame opened above.
g_device->FinishRenderingCurrentFrame();

// --------------------------- Rendering loop -------------------------

HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PLAYGROUNDWIN32));

MSG msg{};

g_device->StartRenderingCurrentFrame();
g_update->Start();

// Main message loop:
while (msg.message != WM_QUIT)
Expand All @@ -388,7 +387,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
if (g_device)
{
// Finish Babylon Native rendering.
g_update->Finish();
g_device->FinishRenderingCurrentFrame();

if (g_selectedModel >= 0)
Expand All @@ -406,7 +404,6 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
// Present and start rendering next frame.
swapChain->Present(1, 0);
g_device->StartRenderingCurrentFrame();
g_update->Start();
}

result = PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE) && msg.message != WM_QUIT;
Expand Down Expand Up @@ -460,7 +457,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
if (g_device)
{
g_update->Finish();
g_device->FinishRenderingCurrentFrame();
}

Expand All @@ -479,7 +475,6 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
if (g_device)
{
g_device->StartRenderingCurrentFrame();
g_update->Start();
}
}
}
Expand Down
3 changes: 0 additions & 3 deletions Apps/UnitTests/Source/Tests.Device.D3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,17 +87,14 @@ TEST(Device, BackBuffer)
config.Height = dimensions[0].cy;

Babylon::Graphics::Device device{config};
Babylon::Graphics::DeviceUpdate update{device.GetUpdate("update")};

for (size_t i = 1; i < std::size(dimensions); ++i)
{
device.StartRenderingCurrentFrame();
update.Start();

device.UpdateBackBuffer(renderTargetTextures[i].View.get());
device.UpdateSize(dimensions[i].cx, dimensions[i].cy);

update.Finish();
device.FinishRenderingCurrentFrame();
}
}
Loading