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
3b32c52
Add external texture array render test and fix numLayers bug
bghgary Mar 25, 2026
117f588
Fix Update signature on Metal, D3D12, and OpenGL backends
bghgary Mar 25, 2026
e616594
Update all callers to use new sync ExternalTexture API
bghgary Mar 25, 2026
2628906
Fix D3D12/Linux builds: guard RenderDoc for D3D11 only, update all ca…
bghgary Mar 25, 2026
0c45a8c
Fix OpenGL build: use portable cast for TextureT to uintptr_t
bghgary Mar 25, 2026
271adaa
Make RenderDoc support API-agnostic (D3D11, D3D12, Vulkan, OpenGL)
bghgary Mar 25, 2026
e103f3e
Remove accidentally committed test artifact
bghgary Mar 25, 2026
bb4ec86
Fix test ordering: finish frame before destroying native texture
bghgary Mar 25, 2026
a1e534c
Add shaderCache.bin to .gitignore
bghgary Mar 25, 2026
38590d9
Fix startup ordering: wait for JS before ending frame
bghgary Mar 25, 2026
92a533c
Fix CI crashes: simplify D3D11 test, revert to single-call texture cr…
bghgary Mar 25, 2026
752cfb8
Fix duplicate test name: rename to CreateForJavaScriptD3D11
bghgary Mar 25, 2026
dfb4018
Remove D3D11-specific ExternalTexture test (covered by cross-platform…
bghgary Mar 25, 2026
1114f20
Log bgfx fatal errors to stderr before crashing
bghgary Mar 25, 2026
0e3f97b
Enable D3D debug layer on CI and revert to _external texture path
bghgary Mar 25, 2026
ba78cdf
Skip render test on CI (WARP SRV issue), keep _external path
bghgary Mar 25, 2026
0d96409
Use overrideInternal for CreateForJavaScript (fixes WARP)
bghgary Mar 25, 2026
3e3abfc
Add extra frame pump in PrecompiledShaderTest for overrideInternal
bghgary Mar 25, 2026
0b309bc
Fix Install CMake, add frame pump to all ExternalTexture callers
bghgary Mar 25, 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
8 changes: 7 additions & 1 deletion .github/jobs/win32.yml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ jobs:

# BGFX_CONFIG_MAX_FRAME_BUFFERS is set so enough Framebuffers are available before V8 starts disposing unused ones
- script: |
cmake -G "Visual Studio 17 2022" -B build/${{variables.solutionName}} -A ${{parameters.platform}} ${{variables.jsEngineDefine}} -D BX_CONFIG_DEBUG=ON -D GRAPHICS_API=${{parameters.graphics_api}} -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D BGFX_CONFIG_MAX_FRAME_BUFFERS=256 -D BABYLON_DEBUG_TRACE=ON -D ENABLE_SANITIZERS=$(SANITIZER_FLAG)
cmake -G "Visual Studio 17 2022" -B build/${{variables.solutionName}} -A ${{parameters.platform}} ${{variables.jsEngineDefine}} -D BX_CONFIG_DEBUG=ON -D GRAPHICS_API=${{parameters.graphics_api}} -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D BGFX_CONFIG_MAX_FRAME_BUFFERS=256 -D BABYLON_DEBUG_TRACE=ON -D ENABLE_SANITIZERS=$(SANITIZER_FLAG) -D BABYLON_NATIVE_SKIP_RENDER_TESTS=ON
displayName: "Generate ${{variables.solutionName}} solution"

- task: MSBuild@1
Expand All @@ -65,6 +65,12 @@ jobs:
reg add "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\UnitTests.exe" /v DumpFolder /t REG_SZ /d "$(Build.ArtifactStagingDirectory)/Dumps" /f
displayName: "Enable Crash Dumps"

- script: |
DISM /online /add-capability /capabilityname:tools.graphics.directx~~~~0.0.1.0 /norestart
d3dconfig debug-layer debug-layer-mode=force-on
displayName: "Enable D3D Debug Layer"
continueOnError: true

- powershell: |
$vs = vswhere -latest -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath
$msvc = Get-ChildItem "$vs\VC\Tools\MSVC" | Sort-Object Name -Descending | Select-Object -First 1
Expand Down
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/build
.DS_Store
.vscode

shaderCache.bin
39 changes: 15 additions & 24 deletions Apps/HeadlessScreenshotApp/Win32/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,41 +127,32 @@ int main()
// Create a render target texture for the output.
winrt::com_ptr<ID3D11Texture2D> outputTexture = CreateD3DRenderTargetTexture(d3dDevice.get());

std::promise<void> addToContext{};
std::promise<void> startup{};

// Create an external texture for the render target texture and pass it to
// the `startup` JavaScript function.
loader.Dispatch([externalTexture = Babylon::Plugins::ExternalTexture{outputTexture.get()}, &addToContext, &startup](Napi::Env env) {
auto jsPromise = externalTexture.AddToContextAsync(env);
addToContext.set_value();

auto jsOnFulfilled = Napi::Function::New(env, [&startup](const Napi::CallbackInfo& info) {
auto nativeTexture = info[0];
info.Env().Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(info.Env(), WIDTH),
Napi::Value::From(info.Env(), HEIGHT),
});
startup.set_value();
});

jsPromise = jsPromise.Get("then").As<Napi::Function>().Call(jsPromise, {jsOnFulfilled}).As<Napi::Promise>();

CatchAndLogError(jsPromise);
loader.Dispatch([externalTexture = Babylon::Plugins::ExternalTexture{outputTexture.get()}, &startup](Napi::Env env) {
auto nativeTexture = externalTexture.CreateForJavaScript(env);
env.Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(env, WIDTH),
Napi::Value::From(env, HEIGHT),
});
startup.set_value();
});

// Wait for `AddToContextAsync` to be called.
addToContext.get_future().wait();

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

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

// Pump an extra frame so overrideInternal applies the native texture.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

struct Asset
{
const char* Name;
Expand Down
38 changes: 15 additions & 23 deletions Apps/PrecompiledShaderTest/Source/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -135,40 +135,32 @@ int RunApp(
Babylon::ScriptLoader loader{runtime};
loader.LoadScript("app:///index.js");

std::promise<void> addToContext{};
std::promise<void> startup{};

// Create an external texture for the render target texture and pass it to
// the `startup` JavaScript function.
loader.Dispatch([externalTexture = std::move(externalTexture), &addToContext, &startup](Napi::Env env) {
auto jsPromise = externalTexture.AddToContextAsync(env);
addToContext.set_value();

auto jsOnFulfilled = Napi::Function::New(env, [&startup](const Napi::CallbackInfo& info) {
auto nativeTexture = info[0];
info.Env().Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(info.Env(), WIDTH),
Napi::Value::From(info.Env(), HEIGHT),
});
startup.set_value();
});

jsPromise = jsPromise.Get("then").As<Napi::Function>().Call(jsPromise, {jsOnFulfilled}).As<Napi::Promise>();
CatchAndLogError(jsPromise);
loader.Dispatch([externalTexture = std::move(externalTexture), &startup](Napi::Env env) {
auto nativeTexture = externalTexture.CreateForJavaScript(env);
env.Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(env, WIDTH),
Napi::Value::From(env, HEIGHT),
});
startup.set_value();
});

// Wait for `AddToContextAsync` to be called.
addToContext.get_future().wait();

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

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

// Pump an extra frame so overrideInternal applies the native texture.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();
deviceUpdate.Finish();
device.FinishRenderingCurrentFrame();

// Start a new frame for rendering the scene.
device.StartRenderingCurrentFrame();
deviceUpdate.Start();
Expand Down
35 changes: 15 additions & 20 deletions Apps/StyleTransferApp/Win32/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,37 +334,32 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
loader.LoadScript("app:///Scripts/babylonjs.loaders.js");
loader.LoadScript("app:///Scripts/index.js");

std::promise<void> addToContext{};
std::promise<void> startup{};

// Create an external texture for the render target texture and pass it to
// the `startup` JavaScript function.
loader.Dispatch([externalTexture = Babylon::Plugins::ExternalTexture{g_BabylonRenderTexture.get()}, &addToContext, &startup](Napi::Env env) {
auto jsPromise = externalTexture.AddToContextAsync(env);
addToContext.set_value();

jsPromise.Get("then").As<Napi::Function>().Call(jsPromise, {Napi::Function::New(env, [&startup](const Napi::CallbackInfo& info) {
auto nativeTexture = info[0];
info.Env().Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(info.Env(), WIDTH),
Napi::Value::From(info.Env(), HEIGHT),
});
startup.set_value();
})});
loader.Dispatch([externalTexture = Babylon::Plugins::ExternalTexture{g_BabylonRenderTexture.get()}, &startup](Napi::Env env) {
auto nativeTexture = externalTexture.CreateForJavaScript(env);
env.Global().Get("startup").As<Napi::Function>().Call(
{
nativeTexture,
Napi::Value::From(env, WIDTH),
Napi::Value::From(env, HEIGHT),
});
startup.set_value();
});

// Wait for `AddToContextAsync` to be called.
addToContext.get_future().wait();

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

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

// Pump an extra frame so overrideInternal applies the native texture.
g_device->StartRenderingCurrentFrame();
g_update->Start();
g_update->Finish();
g_device->FinishRenderingCurrentFrame();

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

HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_PLAYGROUNDWIN32));
Expand Down
16 changes: 13 additions & 3 deletions Apps/UnitTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ if(NOT((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS) OR (UNIX AND NOT AND
endif()

option(BABYLON_NATIVE_TESTS_USE_NOOP_METAL_DEVICE "Use a noop Metal device for Apple platforms." OFF)
option(BABYLON_NATIVE_SKIP_RENDER_TESTS "Skip GPU render tests (e.g. on CI without real GPU)." OFF)

set(BABYLONJS_ASSETS
"../node_modules/babylonjs/babylon.max.js")
Expand All @@ -11,22 +12,23 @@ set(BABYLONJS_MATERIALS_ASSETS
"../node_modules/babylonjs-materials/babylonjs.materials.js")

set(TEST_ASSETS
"JavaScript/dist/tests.externalTexture.render.js"
"JavaScript/dist/tests.javaScript.all.js"
"JavaScript/dist/tests.shaderCache.basicScene.js")

set(SOURCES
"Source/App.h"
"Source/App.cpp"
"Source/Tests.ExternalTexture.cpp"
"Source/Tests.ExternalTexture.Render.cpp"
"Source/Tests.JavaScript.cpp"
"Source/Tests.ShaderCache.cpp"
"Source/Utils.h"
"Source/Utils.${GRAPHICS_API}.${BABYLON_NATIVE_PLATFORM_IMPL_EXT}")

if(GRAPHICS_API STREQUAL "D3D11")
set(SOURCES ${SOURCES}
"Source/Tests.Device.${GRAPHICS_API}.cpp"
"Source/Tests.ExternalTexture.${GRAPHICS_API}.cpp")
"Source/Tests.Device.${GRAPHICS_API}.cpp")
endif()

if(APPLE)
Expand All @@ -42,7 +44,11 @@ elseif(UNIX AND NOT ANDROID)
set(SOURCES ${SOURCES} "Source/App.X11.cpp")
set(ADDITIONAL_COMPILE_DEFINITIONS PRIVATE SKIP_EXTERNAL_TEXTURE_TESTS)
elseif(WIN32)
set(SOURCES ${SOURCES} "Source/App.Win32.cpp")
set(SOURCES ${SOURCES}
"Source/App.Win32.cpp"
"Source/RenderDoc.h"
"Source/RenderDoc.cpp")
set(ADDITIONAL_COMPILE_DEFINITIONS ${ADDITIONAL_COMPILE_DEFINITIONS} PRIVATE HAS_RENDERDOC)
endif()

add_executable(UnitTests ${BABYLONJS_ASSETS} ${BABYLONJS_MATERIALS_ASSETS} ${TEST_ASSETS} ${SOURCES})
Expand All @@ -66,6 +72,10 @@ target_link_libraries(UnitTests

target_compile_definitions(UnitTests PRIVATE ${ADDITIONAL_COMPILE_DEFINITIONS})

if(BABYLON_NATIVE_SKIP_RENDER_TESTS)
target_compile_definitions(UnitTests PRIVATE SKIP_RENDER_TESTS)
endif()

add_test(NAME UnitTests COMMAND UnitTests)

# See https://gitlab.kitware.com/cmake/cmake/-/issues/23543
Expand Down
Loading
Loading