Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
351c87b
enable sanitizers for macOS, Linux and Android
CedricGuillemet Oct 27, 2025
b78acf4
no &&
CedricGuillemet Oct 27, 2025
c2f1138
syntax
CedricGuillemet Oct 27, 2025
ed44d18
job names
CedricGuillemet Oct 27, 2025
a388975
parameters
CedricGuillemet Oct 27, 2025
f46d415
disable unity build
CedricGuillemet Oct 28, 2025
ba0e5c3
missing header, unity build back
CedricGuillemet Oct 28, 2025
121cd8a
linux build
CedricGuillemet Oct 28, 2025
46a5c25
rtti for glslang
CedricGuillemet Oct 28, 2025
a1c6286
Merge branch 'ASAN' of https://github.com/CedricGuillemet/BabylonNati…
CedricGuillemet Oct 28, 2025
2fa6784
android sanitizers
CedricGuillemet Oct 29, 2025
18f0dab
ndk 28
CedricGuillemet Oct 29, 2025
c11fba6
sanitizers for unittests android
CedricGuillemet Oct 29, 2025
f17242c
Merge branch 'master' of https://github.com/babylonjs/BabylonNative i…
CedricGuillemet Nov 13, 2025
8d910e7
removed perf test
CedricGuillemet Nov 13, 2025
8f93ea4
JSRuntimeHost update
CedricGuillemet Nov 13, 2025
55ee800
removed android + sanitizer
CedricGuillemet Nov 14, 2025
816ee5d
Merge branch 'master' of https://github.com/babylonjs/BabylonNative i…
CedricGuillemet Nov 14, 2025
31f815f
disable ubsan for 1 template method
CedricGuillemet Nov 14, 2025
c80dd5c
fix leaks
CedricGuillemet Nov 14, 2025
88724f3
fix casting
CedricGuillemet Nov 14, 2025
9345b67
leaks and warnings
CedricGuillemet Nov 14, 2025
51740d3
early exit
CedricGuillemet Nov 14, 2025
a46ad85
mem leak
CedricGuillemet Nov 14, 2025
654407c
removed union
CedricGuillemet Nov 14, 2025
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
7 changes: 5 additions & 2 deletions .github/jobs/android.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ jobs:
timeoutInMinutes: 45
pool:
vmImage: ${{ parameters.vmImage }}


variables:
SANITIZER_FLAG: ${{ coalesce(replace(format('{0}', parameters.Sanitizers), 'True', 'ON'), 'OFF') }}

steps:
- template: cmake.yml
parameters:
Expand All @@ -26,7 +29,7 @@ jobs:
workingDirectory: 'Apps/Playground/Android'
gradleWrapperFile: 'Apps/Playground/Android/gradlew'
gradleOptions: '-Xmx1536m'
options: '-PJSEngine=${{ parameters.JSEngine }} -PARM64Only -PNDK_VERSION=$(NDK_VERSION)'
options: '-PJSEngine=${{ parameters.JSEngine }} -PARM64Only -PNDK_VERSION=$(NDK_VERSION) -PSANITIZERS=$(SANITIZER_FLAG)'
publishJUnitResults: false
tasks: 'assembleRelease'
displayName: 'Build Playground ${{ parameters.JSEngine }}'
6 changes: 4 additions & 2 deletions .github/jobs/linux.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ parameters:
CC: ''
CXX: ''
JSEngine: ''
enableSanitizers: false

jobs:
- job: ${{ parameters.name }}
Expand All @@ -12,6 +13,7 @@ jobs:
vmImage: ${{ parameters.vmImage }}

variables:
SANITIZER_FLAG: ${{ coalesce(replace(format('{0}', parameters.enableSanitizers), 'True', 'ON'), 'OFF') }}
CC: ${{ parameters.CC }}
CXX: ${{ parameters.CXX }}

Expand All @@ -22,11 +24,11 @@ jobs:

- script: |
sudo apt-get update
sudo apt-get install libjavascriptcoregtk-4.1-dev libgl1-mesa-dev libcurl4-openssl-dev libwayland-dev
sudo apt-get install libjavascriptcoregtk-4.1-dev libgl1-mesa-dev libcurl4-openssl-dev libwayland-dev clang
displayName: 'Install packages'

- script: |
cmake -G Ninja -B build -D JAVASCRIPTCORE_LIBRARY=/usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.1.so -D NAPI_JAVASCRIPT_ENGINE=${{ parameters.JSEngine }} -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BX_CONFIG_DEBUG=ON -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D OpenGL_GL_PREFERENCE=GLVND -D BABYLON_DEBUG_TRACE=ON
cmake -G Ninja -B build -D JAVASCRIPTCORE_LIBRARY=/usr/lib/x86_64-linux-gnu/libjavascriptcoregtk-4.1.so -D NAPI_JAVASCRIPT_ENGINE=${{ parameters.JSEngine }} -D CMAKE_BUILD_TYPE=RelWithDebInfo -D BX_CONFIG_DEBUG=ON -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D OpenGL_GL_PREFERENCE=GLVND -D BABYLON_DEBUG_TRACE=ON -D ENABLE_SANITIZERS=$(SANITIZER_FLAG) .
ninja -C build
displayName: 'Build X11'

Expand Down
8 changes: 6 additions & 2 deletions .github/jobs/macos.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
parameters:
name: ''
vmImage: ''
enableSanitizers: false

jobs:
- job: ${{ parameters.name }}
timeoutInMinutes: 30
pool:
vmImage: ${{ parameters.vmImage }}


variables:
SANITIZER_FLAG: ${{ coalesce(replace(format('{0}', parameters.enableSanitizers), 'True', 'ON'), 'OFF') }}

steps:
- template: cmake.yml
parameters:
Expand All @@ -18,7 +22,7 @@ jobs:
displayName: 'Select XCode $(XCODE_VERSION)'

- script: |
cmake -G Xcode -B buildmacOS -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D BABYLON_DEBUG_TRACE=ON
cmake -G Xcode -B buildmacOS -D CMAKE_UNITY_BUILD=$(UNITY_BUILD) -D BABYLON_DEBUG_TRACE=ON -D ENABLE_SANITIZERS=$(SANITIZER_FLAG)
displayName: 'Generate macOS solution'

- script: |
Expand Down
1 change: 1 addition & 0 deletions Apps/Playground/Android/BabylonNative/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ def unity_build = "false"
if (project.hasProperty("UNITY_BUILD")) {
unity_build = project.property("UNITY_BUILD")
}

def arcore_libpath = "${buildDir}/arcore-native"

configurations { natives }
Expand Down
1 change: 1 addition & 0 deletions Apps/Playground/X11/App.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -296,5 +296,6 @@ int main(int _argc, const char* const* _argv)

XUnmapWindow(display, window);
XDestroyWindow(display, window);
XCloseDisplay(display);
return 0;
}
6 changes: 2 additions & 4 deletions Apps/UnitTests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,11 @@ endif()

set(SCRIPTS
"Scripts/tests.ts"
"Scripts/unittests_performance_shadercache.ts"
"Scripts/unittests_performance_spheres.ts")
"Scripts/unittests_performance_shadercache.ts")

set(BUILD_SCRIPTS
"dist/tests.js"
"dist/unittests_performance_shadercache.js"
"dist/unittests_performance_spheres.js")
"dist/unittests_performance_shadercache.js")

set(SOURCES
"Shared/Shared.h"
Expand Down
33 changes: 0 additions & 33 deletions Apps/UnitTests/Scripts/unittests_performance_spheres.ts

This file was deleted.

85 changes: 0 additions & 85 deletions Apps/UnitTests/Shared/Shared.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,91 +99,6 @@ TEST(JavaScript, All)
EXPECT_EQ(exitCode, 0);
}

/*
This test does a serie of initialization and shutdowns.
It needs the shutdown PR to be merged before running properly.
TEST(NativeAPI, LifeCycle)
{
for (int cycle = 0; cycle < 20; cycle++)
{
Babylon::Graphics::Device device{deviceConfig};
std::optional<Babylon::Polyfills::Canvas> nativeCanvas;
Babylon::AppRuntime runtime{};
runtime.Dispatch([&device, &nativeCanvas](Napi::Env env) {
device.AddToJavaScript(env);
Babylon::Polyfills::XMLHttpRequest::Initialize(env);
Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) {
printf("%s", message);
fflush(stdout);
});
Babylon::Polyfills::Window::Initialize(env);
nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env));
Babylon::Plugins::NativeEngine::Initialize(env);
});
Babylon::ScriptLoader loader{runtime};
loader.LoadScript("app:///Scripts/babylon.max.js");
loader.LoadScript("app:///Scripts/babylonjs.materials.js");
for (int frame = 0; frame < 10; frame++)
{
device.StartRenderingCurrentFrame();
device.FinishRenderingCurrentFrame();
}
}
}
*/

TEST(Performance, Spheres)
{
// create a bunch of sphere, does the rendering for a number of frames, log time it took
Babylon::Graphics::Device device{deviceConfig};
std::optional<Babylon::Graphics::DeviceUpdate> update{};
std::promise<int32_t> ready;
update.emplace(device.GetUpdate("update"));

Babylon::AppRuntime runtime{};
runtime.Dispatch([&ready, &device](Napi::Env env) {
device.AddToJavaScript(env);

Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) {
std::cout << message << std::endl;
std::cout.flush();
});
Babylon::Polyfills::Window::Initialize(env);
Babylon::Plugins::NativeEngine::Initialize(env);
env.Global().Set("setReady", Napi::Function::New(
env, [&ready](const Napi::CallbackInfo& info) {
Napi::Env env = info.Env();
ready.set_value(1);
},
"setReady"));
});

Babylon::ScriptLoader loader{runtime};
loader.LoadScript("app:///Scripts/unittests_performance_spheres.js");

ready.get_future().get();

const auto start = std::chrono::high_resolution_clock::now();

for (int frame = 0; frame < 100; frame++)
{
device.StartRenderingCurrentFrame();
update->Start();
update->Finish();
device.FinishRenderingCurrentFrame();
}
// Stop measuring time
const auto stop = std::chrono::high_resolution_clock::now();
const auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(stop - start);
const float durationSeconds = float(duration.count()) / 1000.f;
std::cout << "Duration is " << durationSeconds << " seconds. " << std::endl;
std::cout.flush();
}

TEST(Performance, ShaderCache)
{
Babylon::ShaderCache::Enabled(true);
Expand Down
1 change: 0 additions & 1 deletion Apps/UnitTests/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ module.exports = {
entry: {
tests: './Scripts/tests.ts',
unittests_performance_shadercache: './Scripts/unittests_performance_shadercache.ts',
unittests_performance_spheres: './Scripts/unittests_performance_spheres.ts',
},
output: {
filename: '[name].js',
Expand Down
28 changes: 26 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ include(FetchContent)
# --------------------------------------------------
FetchContent_Declare(AndroidExtensions
GIT_REPOSITORY https://github.com/BabylonJS/AndroidExtensions.git
GIT_TAG 66520bff9b57030b67894a4934d18ad7e161ba6f)
GIT_TAG f7ed149b5360cc8a4908fece66607c5ce1e6095b)
FetchContent_Declare(arcana.cpp
GIT_REPOSITORY https://github.com/microsoft/arcana.cpp.git
GIT_TAG c726dbe58713eda65bfb139c257093c43479b894)
Expand All @@ -37,7 +37,7 @@ FetchContent_Declare(ios-cmake
GIT_TAG 4.5.0)
FetchContent_Declare(JsRuntimeHost
GIT_REPOSITORY https://github.com/BabylonJS/JsRuntimeHost.git
GIT_TAG 7964539e733a5cd2cbae7e0155f5391d64a9d45d)
GIT_TAG 70ba1e53d386c3f50727d6586c71aece614ff08b)
FetchContent_Declare(SPIRV-Cross
GIT_REPOSITORY https://github.com/BabylonJS/SPIRV-Cross.git
GIT_TAG 6abfcf066d171e9ade7604d91381ebebe4209edc)
Expand Down Expand Up @@ -107,6 +107,30 @@ option(BABYLON_NATIVE_PLUGIN_TESTUTILS "Include Babylon Native Plugin TestUtils.
option(BABYLON_NATIVE_POLYFILL_WINDOW "Include Babylon Native Polyfill Window." ON)
option(BABYLON_NATIVE_POLYFILL_CANVAS "Include Babylon Native Polyfill Canvas." ON)

# Sanitizers
option(ENABLE_SANITIZERS "Enable AddressSanitizer and UBSan" OFF)

if(ENABLE_SANITIZERS)
set(ENABLE_RTTI ON CACHE BOOL "" FORCE)
if(CMAKE_CXX_COMPILER_ID MATCHES "Clang|GNU")
set(SANITIZERS "address,undefined")
# Check for Clang since vptr and fdsan are Clang-specific
if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
list(APPEND SANITIZERS "vptr")
# FDSan only works on Android builds with Clang
if (ANDROID)
list(APPEND SANITIZERS "fdsan")
endif()
endif()

string(JOIN "," SANITIZER_FLAGS ${SANITIZERS})

add_compile_options(-fsanitize=${SANITIZER_FLAGS} -fno-omit-frame-pointer)
add_link_options(-fsanitize=${SANITIZER_FLAGS})
else()
message(WARNING "Sanitizers not supported on this compiler.")
endif()
endif()
# --------------------------------------------------

if(ANDROID)
Expand Down
2 changes: 2 additions & 0 deletions Core/Graphics/Source/DeviceImpl_Unix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ namespace Babylon::Graphics
auto width = DisplayWidthMM(display, screen);
auto pixelWidth = DisplayWidth(display, screen);

XCloseDisplay(display);

if (width > 0)
{
constexpr float MILLIMETERS_TO_INCHES = 0.03937f;
Expand Down
6 changes: 6 additions & 0 deletions Plugins/NativeEngine/Source/NativeDataStream.h
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ namespace Babylon
}

template<typename T>
#ifndef _MSC_VER
// Clang reports UndefinedBehaviorSanitizer : undefined - behavior
// load of misaligned address which requires 8 byte alignment
// pointed data are fine so it looks like a false positive
__attribute__((no_sanitize("undefined")))
#endif
T ReadNativeData()
{
Validate<ValidationType::NativeData>(*this);
Expand Down
6 changes: 4 additions & 2 deletions Plugins/TestUtils/Source/Unix/TestUtilsImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ namespace Babylon::Plugins::Internal
auto window = (Window)m_implData->m_window;
const int32_t exitCode = info[0].As<Napi::Number>().Int32Value();
Plugins::TestUtils::errorCode = exitCode;
Display* display = XOpenDisplay(NULL);
auto display = XOpenDisplay(NULL);
XClientMessageEvent dummyEvent;
memset(&dummyEvent, 0, sizeof(XClientMessageEvent));
dummyEvent.type = ClientMessage;
Expand All @@ -29,6 +29,7 @@ namespace Babylon::Plugins::Internal
dummyEvent.data.l[0] = XInternAtom(display, "WM_DELETE_WINDOW", False);;
XSendEvent(display, window, 0, 0, (XEvent*)&dummyEvent);
XFlush(display);
XCloseDisplay(display);
}

void TestUtils::UpdateSize(const Napi::CallbackInfo& /*info*/)
Expand All @@ -38,9 +39,10 @@ namespace Babylon::Plugins::Internal
void TestUtils::SetTitle(const Napi::CallbackInfo& info)
{
const auto title = info[0].As<Napi::String>().Utf8Value();
Display* display = XOpenDisplay(NULL);
auto display = XOpenDisplay(NULL);
auto window = (Window)m_implData->m_window;
XStoreName(display, window, title.c_str());
XCloseDisplay(display);
}

Napi::Value TestUtils::GetOutputDirectory(const Napi::CallbackInfo& info)
Expand Down
8 changes: 4 additions & 4 deletions Polyfills/Canvas/Source/Gradient.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -285,12 +285,12 @@ namespace Babylon::Polyfills::Internal
}
else
{
int w = (int)fabsf(g);
int w = (int)std::fabs(g);
if (spreadMode == SPREAD_REPEAT)
{
if (g < 0)
{
g = 1 - (fabs(g) - w);
g = 1 - (std::fabs(g) - w);
}
else
{
Expand All @@ -303,11 +303,11 @@ namespace Babylon::Polyfills::Internal
{
if (w % 2 == 0)
{ // even
g = (fabsf(g) - w);
g = (std::fabs(g) - w);
}
else
{ // odd
g = (1 - (fabsf(g) - w));
g = (1 - (std::fabs(g) - w));
}
}
else
Expand Down
Loading
Loading