diff --git a/.github/jobs/android.yml b/.github/jobs/android.yml index c2f9e8f7b..3de909ab4 100644 --- a/.github/jobs/android.yml +++ b/.github/jobs/android.yml @@ -15,6 +15,34 @@ jobs: parameters: vmImage: ${{ parameters.vmImage }} + - script: | + set -euo pipefail + ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}" + if [ -z "$ANDROID_SDK_ROOT" ]; then + echo "ANDROID_SDK_ROOT or ANDROID_HOME must be set" >&2 + exit 1 + fi + + if [ -x "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" + elif [ -x "$ANDROID_SDK_ROOT/cmdline-tools/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/bin/sdkmanager" + elif [ -x "$ANDROID_SDK_ROOT/tools/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/tools/bin/sdkmanager" + else + echo "Unable to locate sdkmanager under $ANDROID_SDK_ROOT" >&2 + exit 1 + fi + + echo "Installing Android NDK version $(NDK_VERSION) using $SDKMANAGER" + SDK_ARGS=("--sdk_root=$ANDROID_SDK_ROOT") + + set +o pipefail + yes | "$SDKMANAGER" "${SDK_ARGS[@]}" --licenses >/dev/null + yes | "$SDKMANAGER" "${SDK_ARGS[@]}" --install "ndk;$(NDK_VERSION)" + set -o pipefail + displayName: 'Install Android NDK $(NDK_VERSION)' + - task: JavaToolInstaller@0 inputs: versionSpec: '17' diff --git a/.github/jobs/android_tests.yml b/.github/jobs/android_tests.yml index c18691022..47be0ff74 100644 --- a/.github/jobs/android_tests.yml +++ b/.github/jobs/android_tests.yml @@ -15,6 +15,34 @@ jobs: parameters: vmImage: ${{ parameters.vmImage }} + - script: | + set -euo pipefail + ANDROID_SDK_ROOT="${ANDROID_SDK_ROOT:-${ANDROID_HOME:-}}" + if [ -z "$ANDROID_SDK_ROOT" ]; then + echo "ANDROID_SDK_ROOT or ANDROID_HOME must be set" >&2 + exit 1 + fi + + if [ -x "$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/latest/bin/sdkmanager" + elif [ -x "$ANDROID_SDK_ROOT/cmdline-tools/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/cmdline-tools/bin/sdkmanager" + elif [ -x "$ANDROID_SDK_ROOT/tools/bin/sdkmanager" ]; then + SDKMANAGER="$ANDROID_SDK_ROOT/tools/bin/sdkmanager" + else + echo "Unable to locate sdkmanager under $ANDROID_SDK_ROOT" >&2 + exit 1 + fi + + echo "Installing Android NDK version $(NDK_VERSION) using $SDKMANAGER" + SDK_ARGS=("--sdk_root=$ANDROID_SDK_ROOT") + + set +o pipefail + yes | "$SDKMANAGER" "${SDK_ARGS[@]}" --licenses >/dev/null + yes | "$SDKMANAGER" "${SDK_ARGS[@]}" --install "ndk;$(NDK_VERSION)" + set -o pipefail + displayName: 'Install Android NDK $(NDK_VERSION)' + - script: | echo Install Android image echo 'y' | $ANDROID_HOME/tools/bin/sdkmanager --install 'system-images;android-27;default;x86_64' diff --git a/.github/jobs/win32.yml b/.github/jobs/win32.yml index e73090f71..f716c63d4 100644 --- a/.github/jobs/win32.yml +++ b/.github/jobs/win32.yml @@ -18,7 +18,7 @@ parameters: jobs: - job: ${{ parameters.name }} - timeoutInMinutes: 20 + timeoutInMinutes: 60 pool: vmImage: ${{ parameters.vmImage }} variables: diff --git a/.gitignore b/.gitignore index 087c17bff..20514dfc8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ /build .DS_Store .vscode - +dist/ diff --git a/Apps/Playground/Android/BabylonNative/build.gradle b/Apps/Playground/Android/BabylonNative/build.gradle index 11486d023..daf526bf0 100644 --- a/Apps/Playground/Android/BabylonNative/build.gradle +++ b/Apps/Playground/Android/BabylonNative/build.gradle @@ -22,6 +22,9 @@ if (project.hasProperty("UNITY_BUILD")) { } def arcore_libpath = "${buildDir}/arcore-native" +def deviceAbis = project.hasProperty("ARM64Only") ? ["arm64-v8a"] : ["arm64-v8a", "armeabi-v7a", "x86"] +def xrSimulatorAbis = ["arm64-v8a"] + configurations { natives } android { @@ -31,16 +34,15 @@ android { defaultConfig { minSdk 25 - testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" consumerProguardFiles "consumer-rules.pro" - ndkVersion "23.1.7779620" + ndkVersion "28.2.13676358" if (project.hasProperty("NDK_VERSION")) { def NDKVersion = project.property("NDK_VERSION") ndkVersion "${NDK_VERSION}" } externalNativeBuild { cmake { - abiFilters "arm64-v8a", "armeabi-v7a", "x86", "x86_64" arguments "-DANDROID_STL=c++_shared", "-DENABLE_PCH=OFF", "-DGRAPHICS_API=${graphics_api}", @@ -51,18 +53,39 @@ android { "-DBABYLON_DEBUG_TRACE=ON" } } - ndk { - if (project.hasProperty("ARM64Only")) { - abiFilters "arm64-v8a" - } else { - abiFilters "arm64-v8a", "armeabi-v7a", "x86" - } - } packagingOptions { exclude '**/libarcore_sdk_c.so' } } + flavorDimensions "runtime" + productFlavors { + device { + dimension "runtime" + ndk { + abiFilters.addAll(deviceAbis) + } + externalNativeBuild { + cmake { + abiFilters.clear() + abiFilters.addAll(deviceAbis) + } + } + } + androidXrSimulator { + dimension "runtime" + ndk { + abiFilters.addAll(xrSimulatorAbis) + } + externalNativeBuild { + cmake { + abiFilters.clear() + abiFilters.addAll(xrSimulatorAbis) + } + } + } + } + externalNativeBuild { cmake { version '3.19.6+' @@ -92,10 +115,11 @@ dependencies { // ARCore library implementation 'com.google.ar:core:1.14.0' natives 'com.google.ar:core:1.14.0' - implementation 'com.android.support:appcompat-v7:28.0.0' + implementation 'androidx.appcompat:appcompat:1.6.1' testImplementation 'junit:junit:4.13.2' - androidTestImplementation 'com.android.support.test:runner:1.0.2' - androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' + androidTestImplementation 'androidx.test:runner:1.5.2' + androidTestImplementation 'androidx.test.ext:junit:1.1.5' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1' } diff --git a/Apps/Playground/Android/BabylonNative/src/androidTest/java/com/example/babylonnative/ExampleInstrumentedTest.java b/Apps/Playground/Android/BabylonNative/src/androidTest/java/com/example/babylonnative/ExampleInstrumentedTest.java index 1be1dc04b..290346d94 100644 --- a/Apps/Playground/Android/BabylonNative/src/androidTest/java/com/example/babylonnative/ExampleInstrumentedTest.java +++ b/Apps/Playground/Android/BabylonNative/src/androidTest/java/com/example/babylonnative/ExampleInstrumentedTest.java @@ -1,8 +1,8 @@ package com.example.babylonnative; import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.platform.app.InstrumentationRegistry; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/Apps/Playground/Android/app/build.gradle b/Apps/Playground/Android/app/build.gradle index c2a4dd72e..ed39e3e12 100644 --- a/Apps/Playground/Android/app/build.gradle +++ b/Apps/Playground/Android/app/build.gradle @@ -15,22 +15,41 @@ if (project.hasProperty("UNITY_BUILD")) { } def arcore_libpath = "${buildDir}/arcore-native" +def deviceAbis = project.hasProperty("ARM64Only") ? ["arm64-v8a"] : ["arm64-v8a", "armeabi-v7a", "x86"] +def xrSimulatorAbis = ["arm64-v8a"] + configurations { natives } android { - compileSdkVersion 29 + compileSdk 34 defaultConfig { applicationId "com.android.babylonnative.playground" - minSdkVersion "${platformVersion}" - targetSdkVersion 29 - ndkVersion "23.1.7779620" + minSdk platformVersion + targetSdk 34 + ndkVersion "28.2.13676358" if (project.hasProperty("NDK_VERSION")) { def NDKVersion = project.property("NDK_VERSION") ndkVersion "${NDK_VERSION}" } } + flavorDimensions "runtime" + productFlavors { + device { + dimension "runtime" + ndk { + abiFilters.addAll(deviceAbis) + } + } + androidXrSimulator { + dimension "runtime" + ndk { + abiFilters.addAll(xrSimulatorAbis) + } + } + } + packagingOptions { jniLibs { pickFirsts += ['lib/*/libv8android.so', 'lib/*/libjsc.so', 'lib/*/libBabylonNativeJNI.so', 'lib/*/libc++_shared.so'] @@ -62,8 +81,8 @@ dependencies { implementation project(':BabylonNative') natives 'com.google.ar:core:1.14.0' - implementation 'com.android.support:appcompat-v7:27.1.1' - implementation 'com.android.support:design:27.1.1' + implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'com.google.android.material:material:1.10.0' } // Extracts the shared libraries from aars in the natives configuration. diff --git a/Apps/Playground/Android/app/src/main/AndroidManifest.xml b/Apps/Playground/Android/app/src/main/AndroidManifest.xml index f33bace11..2959fb0a9 100644 --- a/Apps/Playground/Android/app/src/main/AndroidManifest.xml +++ b/Apps/Playground/Android/app/src/main/AndroidManifest.xml @@ -22,6 +22,7 @@ android:icon="@mipmap/ic_launcher" android:label="@string/playground_activity"> diff --git a/Apps/Playground/Android/app/src/main/java/com/android/babylonnative/playground/PlaygroundActivity.java b/Apps/Playground/Android/app/src/main/java/com/android/babylonnative/playground/PlaygroundActivity.java index 3064c14b7..0916e6860 100644 --- a/Apps/Playground/Android/app/src/main/java/com/android/babylonnative/playground/PlaygroundActivity.java +++ b/Apps/Playground/Android/app/src/main/java/com/android/babylonnative/playground/PlaygroundActivity.java @@ -4,8 +4,8 @@ import android.app.Activity; import android.content.pm.PackageManager; import android.os.Bundle; -import android.support.v4.app.ActivityCompat; -import android.support.v4.content.ContextCompat; +import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import android.view.View; import com.library.babylonnative.BabylonView; diff --git a/Apps/Playground/Android/gradle.properties b/Apps/Playground/Android/gradle.properties index f6bd6dd09..4ad771bd8 100644 --- a/Apps/Playground/Android/gradle.properties +++ b/Apps/Playground/Android/gradle.properties @@ -12,3 +12,5 @@ org.gradle.jvmargs=-Xmx1536m # http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects # org.gradle.parallel=true # jsEngine=JavaScriptCore +android.useAndroidX=true +android.enableJetifier=true diff --git a/Apps/Playground/Android/gradlew b/Apps/Playground/Android/gradlew old mode 100644 new mode 100755 diff --git a/Apps/Playground/Scripts/config.json b/Apps/Playground/Scripts/config.json index c3d0df315..7f04d238d 100644 --- a/Apps/Playground/Scripts/config.json +++ b/Apps/Playground/Scripts/config.json @@ -115,9 +115,9 @@ "title": "Glow layer and LODs", "playgroundId": "#UNS6ZV#2", "renderCount": 50, - "excludedGraphicsApis": [ "OpenGL" ], + "excludedGraphicsApis": [ "OpenGL", "D3D12" ], "referenceImage": "glowlayerandlods.png", - "comment": "xvfb : invalid enum with glRenderbufferStorage" + "comment": "xvfb : invalid enum with glRenderbufferStorage. D3D12/CI: mapping a texture fails with error HRESULT 0x887A0005" }, { "title": "Nested BBG", @@ -128,7 +128,9 @@ { "title": "Dynamic Texture context clip", "playgroundId": "#FU0ES5#47", - "referenceImage": "dynamicTextureClip.png" + "referenceImage": "dynamicTextureClip.png", + "excludedGraphicsApis": ["D3D12" ], + "comment": "D3D12/CI: Incorrect rendering of clipped texture" }, { "title": "GUI3D SpherePanel", diff --git a/Apps/Playground/Scripts/validation_native.js b/Apps/Playground/Scripts/validation_native.js index be67a4f1c..7445c3c7d 100644 --- a/Apps/Playground/Scripts/validation_native.js +++ b/Apps/Playground/Scripts/validation_native.js @@ -81,7 +81,7 @@ } function evaluate(test, referenceImage, done, compareFunction) { - engine._engine.getFrameBufferData(function (screenshot) { + TestUtils.getFrameBufferData(function (screenshot) { let testRes = true; if (!test.onlyVisual) { diff --git a/Apps/package-lock.json b/Apps/package-lock.json index 52a47cb42..1b632a635 100644 --- a/Apps/package-lock.json +++ b/Apps/package-lock.json @@ -11,11 +11,11 @@ "UnitTests" ], "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0", - "babylonjs-gui": "^8.17.0", - "babylonjs-loaders": "^8.17.0", - "babylonjs-materials": "^8.17.0", + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2", + "babylonjs-gui": "^8.28.2", + "babylonjs-loaders": "^8.28.2", + "babylonjs-materials": "^8.28.2", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } @@ -95,6 +95,7 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1924,7 +1925,8 @@ "version": "8.25.1", "resolved": "https://registry.npmjs.org/@babylonjs/core/-/core-8.25.1.tgz", "integrity": "sha512-MxnXfRzHe/JzkGz1w/rtmLaU/m93aatqgOnMiXP6lP7a81LodA5nxL48KTHcIgz3cf5ChFr8n2qNkCjc049NIA==", - "license": "Apache-2.0" + "license": "Apache-2.0", + "peer": true }, "node_modules/@babylonjs/gui": { "version": "8.25.1", @@ -2402,6 +2404,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -2428,6 +2431,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -2600,44 +2604,45 @@ } }, "node_modules/babylonjs": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.17.0.tgz", - "integrity": "sha512-XLMAk+R/9wZMhwdRZFGO6z8rrJvvvhsiztHA0NLvi9hcdxbsdTwA4Ic5Rscqy+9O11hWSBjjuEuGsSrVXdJZDg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs/-/babylonjs-8.28.2.tgz", + "integrity": "sha512-mid1cYg2VGXKj4neNy+78MHwSV8tMCHbvSEaIXQuEj1JxKmEb+UQ6/XwqiSGMrw1IoFxRZ693kelfe1tuSdKJg==", "hasInstallScript": true, "license": "Apache-2.0" }, "node_modules/babylonjs-gltf2interface": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.17.0.tgz", - "integrity": "sha512-EdfH3PTIY5U1Y+gUj/mSw/fW+fUvTEZWryOBaXF4nwZzaFOfhnG/+kJ1gNEE25lNbOHOYlYw0k0S6eMaw1UJBA==", - "license": "Apache-2.0" + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-gltf2interface/-/babylonjs-gltf2interface-8.28.2.tgz", + "integrity": "sha512-TGusApjAPNkPhyyU/05FNoiEc9l85Kd4ZGHO/5hsRkLLYVXvmsqAEa9yGIVLhYM3Yezf/b1DFwMPvY1D/NEiVA==", + "license": "Apache-2.0", + "peer": true }, "node_modules/babylonjs-gui": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.17.0.tgz", - "integrity": "sha512-8pYk22jPkeOJGKZpgdox9CK+FmdZO5w9MbVMaCCYeodtAS/9QhETYsdd4LuWG7hHhFITaiIDn9FnlyaclbMTrg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-gui/-/babylonjs-gui-8.28.2.tgz", + "integrity": "sha512-sFURHbGEfPiRPGQM4jKsPbG4ZxWj9cejNbaxbjNMCB8izc33rzXB67+yHxDdSfjkiEeB1VM30OdhdEW6/JAq+g==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0" + "babylonjs": "^8.28.2" } }, "node_modules/babylonjs-loaders": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.17.0.tgz", - "integrity": "sha512-mkEw4aXIkPI4Ef/Wjvdv6L2UVvQ2bINYpdflYqzo77biWCm0Oq5H/QODYgnHv/EUe0RGPgGbO+T8HyLtUsb8lg==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-loaders/-/babylonjs-loaders-8.28.2.tgz", + "integrity": "sha512-WIbR3gaHhxSvRzs7Yuz578YlhPXqlB36tEEqIo0E+s5FqgzFy+o2TBN0O8nWnGuyk7s4wAZpA8CBQ58KsGfw5Q==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0" + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2" } }, "node_modules/babylonjs-materials": { - "version": "8.17.0", - "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.17.0.tgz", - "integrity": "sha512-iS6gUSUlhNUcKlmaVvXq0PyrGmYR+LyVr3uSpIVUKm9svZ/fAsZEEQ+riRRKFYGdsUnhfqDVPsHv2YSfoLNQgA==", + "version": "8.28.2", + "resolved": "https://registry.npmjs.org/babylonjs-materials/-/babylonjs-materials-8.28.2.tgz", + "integrity": "sha512-5/pURv40ugE7tIeiuW/6C4Eo6VXOcHZJhtjrwdLDlpfMFpAU7d2JTNyaa9NqnHkRVRqXtad3/cu6FoVw6+AsZw==", "license": "Apache-2.0", "dependencies": { - "babylonjs": "^8.17.0" + "babylonjs": "^8.28.2" } }, "node_modules/balanced-match": { @@ -2732,6 +2737,7 @@ } ], "license": "MIT", + "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -5280,6 +5286,7 @@ "integrity": "sha512-7b0dTKR3Ed//AD/6kkx/o7duS8H3f1a4w3BYpIriX4BzIhjkn4teo05cptsxvLesHFKK5KObnadmCHBwGc+51A==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@types/eslint-scope": "^3.7.7", "@types/estree": "^1.0.8", @@ -5329,6 +5336,7 @@ "integrity": "sha512-MfwFQ6SfwinsUVi0rNJm7rHZ31GyTcpVE5pgVA3hwFRb7COD4TzjUUwhGWKfO50+xdc2MQPuEBBJoqIMGt3JDw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@discoveryjs/json-ext": "^0.6.1", "@webpack-cli/configtest": "^3.0.1", diff --git a/Apps/package.json b/Apps/package.json index 3eb661afa..10eb897c7 100644 --- a/Apps/package.json +++ b/Apps/package.json @@ -9,11 +9,11 @@ "getNightly": "node scripts/getNightly.js" }, "dependencies": { - "babylonjs": "^8.17.0", - "babylonjs-gltf2interface": "^8.17.0", - "babylonjs-gui": "^8.17.0", - "babylonjs-loaders": "^8.17.0", - "babylonjs-materials": "^8.17.0", + "babylonjs": "^8.28.2", + "babylonjs-gltf2interface": "^8.28.2", + "babylonjs-gui": "^8.28.2", + "babylonjs-loaders": "^8.28.2", + "babylonjs-materials": "^8.28.2", "jsc-android": "^241213.1.0", "v8-android": "^7.8.2" } diff --git a/CMakeLists.txt b/CMakeLists.txt index 624a9c9f2..983b584dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,8 +36,8 @@ FetchContent_Declare(ios-cmake GIT_REPOSITORY https://github.com/leetal/ios-cmake.git GIT_TAG 4.5.0) FetchContent_Declare(JsRuntimeHost - GIT_REPOSITORY https://github.com/BabylonJS/JsRuntimeHost.git - GIT_TAG ef57990dc5533990b2bb194978a12f8c8d83565c) + GIT_REPOSITORY https://github.com/rebeckerspecialties/JsRuntimeHost.git + GIT_TAG update-jsruntimehost-for-android-xr-compatibility) FetchContent_Declare(SPIRV-Cross GIT_REPOSITORY https://github.com/BabylonJS/SPIRV-Cross.git GIT_TAG 6abfcf066d171e9ade7604d91381ebebe4209edc) diff --git a/Install/Test/CMakeLists.txt b/Install/Test/CMakeLists.txt index ae9523e1d..299093841 100644 --- a/Install/Test/CMakeLists.txt +++ b/Install/Test/CMakeLists.txt @@ -35,22 +35,60 @@ if(MSVC) add_compile_options(/Zc:__cplusplus) endif() +set(USE_SYSTEM_V8 FALSE) +if(ANDROID) + set(_V8_INCLUDE_HINTS) + if(DEFINED ENV{V8_INCLUDE_DIR}) + list(APPEND _V8_INCLUDE_HINTS $ENV{V8_INCLUDE_DIR}) + endif() + if(DEFINED V8_INCLUDE_DIR) + list(APPEND _V8_INCLUDE_HINTS ${V8_INCLUDE_DIR}) + endif() + + find_path(SYSTEM_V8_INCLUDE_DIR + NAMES v8.h + HINTS ${_V8_INCLUDE_HINTS}) + + if(SYSTEM_V8_INCLUDE_DIR) + set(_V8_LIB_HINTS) + if(DEFINED ENV{V8_LIB_DIR}) + list(APPEND _V8_LIB_HINTS $ENV{V8_LIB_DIR}) + endif() + if(DEFINED V8_LIB_DIR) + list(APPEND _V8_LIB_HINTS ${V8_LIB_DIR}) + endif() + + find_library(SYSTEM_V8_MONOLITH_LIB NAMES v8_monolith v8 HINTS ${_V8_LIB_HINTS}) + find_library(SYSTEM_V8_LIBBASE_LIB NAMES v8_libbase HINTS ${_V8_LIB_HINTS}) + find_library(SYSTEM_V8_LIBPLATFORM_LIB NAMES v8_libplatform HINTS ${_V8_LIB_HINTS}) + find_library(SYSTEM_V8_ICUUC_LIB NAMES icuuc HINTS ${_V8_LIB_HINTS}) + find_library(SYSTEM_V8_ICUI18N_LIB NAMES icui18n HINTS ${_V8_LIB_HINTS}) + find_library(SYSTEM_V8_ZLIB_LIB NAMES z zlib HINTS ${_V8_LIB_HINTS}) + + if(SYSTEM_V8_MONOLITH_LIB) + set(USE_SYSTEM_V8 TRUE) + endif() + endif() +endif() + if(NAPI_JAVASCRIPT_ENGINE STREQUAL "") - message("No JS Engine provided. Defaulting to Chakra.") - set(NAPI_JAVASCRIPT_ENGINE "Chakra") + if(APPLE) + message(STATUS "No JS Engine provided. Defaulting to JavaScriptCore on Apple platforms.") + set(NAPI_JAVASCRIPT_ENGINE "JavaScriptCore") + elseif(ANDROID AND USE_SYSTEM_V8) + message(STATUS "No JS Engine provided. Defaulting to system-installed V8 for Android builds.") + set(NAPI_JAVASCRIPT_ENGINE "V8") + else() + message("No JS Engine provided. Defaulting to Chakra.") + set(NAPI_JAVASCRIPT_ENGINE "Chakra") + endif() endif() # executable stub set(APPS_DIR "../../Apps") set(UNITTESTS_DIR "${APPS_DIR}/UnitTests") -set(LOCAL_SCRIPTS "${UNITTESTS_DIR}/Scripts/tests.js") - -set(NPM_SCRIPTS - "${APPS_DIR}/node_modules/babylonjs/babylon.max.js" - "${APPS_DIR}/node_modules/babylonjs-materials/babylonjs.materials.js" - "${APPS_DIR}/node_modules/chai/chai.js" - "${APPS_DIR}/node_modules/mocha/mocha.js") +set(LOCAL_SCRIPTS "${UNITTESTS_DIR}/dist/tests.js") set(SOURCES "${UNITTESTS_DIR}/Shared/Shared.h" @@ -73,64 +111,99 @@ if(NAPI_JAVASCRIPT_ENGINE STREQUAL "JSI") set(SOURCES ${SOURCES} "${V8JSI_PACKAGE_PATH}/build/native/jsi/jsi/jsi.cpp") set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} "v8jsi.dll.lib") elseif(NAPI_JAVASCRIPT_ENGINE STREQUAL "V8") - set_cpu_platform_arch() - set(V8_VERSION "11.9.169.4") - download_nuget() - set(V8_PACKAGE_PATH "${NUGET_PATH}/packages/v8-v143-${CPU_ARCH}.${V8_VERSION}") - set(V8_PACKAGE_PATH "${NUGET_PATH}/packages/v8-v143-${CPU_ARCH}.${V8_VERSION}") - set(V8_REDIST_PACKAGE_PATH "${NUGET_PATH}/packages/v8.redist-v143-${CPU_ARCH}.${V8_VERSION}") - - add_library(v8_libbase SHARED IMPORTED) - set_target_properties(v8_libbase PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libbase.dll.lib") - add_library(v8_libplatform SHARED IMPORTED) - set_target_properties(v8_libplatform PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libplatform.dll.lib") - add_library(v8 SHARED IMPORTED) - set_target_properties(v8 PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8.dll.lib") - target_link_libraries(v8 INTERFACE v8_libbase INTERFACE v8_libplatform) - target_include_directories(v8 INTERFACE "${V8_PACKAGE_PATH}/include") - - set(V8_DIST - "${V8_REDIST_PACKAGE_PATH}/lib/Release/icudtl.dat" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_icu_icui18n.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_abseil-cpp_absl.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/icuuc.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libbase.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libplatform.dll" - "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_zlib.dll") - - # only 1 imported location per library -> Adding 1 library per file - foreach(V8FILE ${V8_DIST}) - get_filename_component(V8FILE_NAME "${V8FILE}" NAME_WE) - add_library("v8::${V8FILE_NAME}" SHARED IMPORTED) - set_target_properties("v8::${V8FILE_NAME}" PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libbase.dll.lib") - set_target_properties("v8::${V8FILE_NAME}" PROPERTIES IMPORTED_LOCATION ${V8FILE}) - endforeach() - - set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} - v8 - v8inspector - llhttp - v8::icudtl - v8::third_party_icu_icui18n - v8::icuuc - v8::v8 - v8::v8_libbase - v8::v8_libplatform - v8::third_party_zlib) - - if(CPU_ARCH STREQUAL "x64") - # Enable V8 Pointer Compression - # https://v8.dev/blog/pointer-compression - # https://stackoverflow.com/q/62921373 - set(NAPI_DEFINITIONS PUBLIC V8_COMPRESS_POINTERS) + if(USE_SYSTEM_V8 AND NOT WIN32) + message(STATUS "Linking against system-installed V8 libraries from ${SYSTEM_V8_MONOLITH_LIB}") + set(V8_INCLUDE_DIR ${SYSTEM_V8_INCLUDE_DIR}) + + set(_SYSTEM_V8_LIBS ${SYSTEM_V8_MONOLITH_LIB}) + if(SYSTEM_V8_LIBBASE_LIB) + list(APPEND _SYSTEM_V8_LIBS ${SYSTEM_V8_LIBBASE_LIB}) + endif() + if(SYSTEM_V8_LIBPLATFORM_LIB) + list(APPEND _SYSTEM_V8_LIBS ${SYSTEM_V8_LIBPLATFORM_LIB}) + endif() + if(SYSTEM_V8_ICUUC_LIB) + list(APPEND _SYSTEM_V8_LIBS ${SYSTEM_V8_ICUUC_LIB}) + endif() + if(SYSTEM_V8_ICUI18N_LIB) + list(APPEND _SYSTEM_V8_LIBS ${SYSTEM_V8_ICUI18N_LIB}) + endif() + if(SYSTEM_V8_ZLIB_LIB) + list(APPEND _SYSTEM_V8_LIBS ${SYSTEM_V8_ZLIB_LIB}) + endif() + + find_package(Threads REQUIRED) + if(CMAKE_THREAD_LIBS_INIT) + list(APPEND _SYSTEM_V8_LIBS ${CMAKE_THREAD_LIBS_INIT}) + endif() + if(UNIX AND NOT APPLE) + list(APPEND _SYSTEM_V8_LIBS dl) + endif() + + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} ${_SYSTEM_V8_LIBS}) + else() + set_cpu_platform_arch() + set(V8_VERSION "11.9.169.4") + download_nuget() + set(V8_PACKAGE_PATH "${NUGET_PATH}/packages/v8-v143-${CPU_ARCH}.${V8_VERSION}") + set(V8_PACKAGE_PATH "${NUGET_PATH}/packages/v8-v143-${CPU_ARCH}.${V8_VERSION}") + set(V8_REDIST_PACKAGE_PATH "${NUGET_PATH}/packages/v8.redist-v143-${CPU_ARCH}.${V8_VERSION}") + + add_library(v8_libbase SHARED IMPORTED) + set_target_properties(v8_libbase PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libbase.dll.lib") + add_library(v8_libplatform SHARED IMPORTED) + set_target_properties(v8_libplatform PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libplatform.dll.lib") + add_library(v8 SHARED IMPORTED) + set_target_properties(v8 PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8.dll.lib") + target_link_libraries(v8 INTERFACE v8_libbase INTERFACE v8_libplatform) + target_include_directories(v8 INTERFACE "${V8_PACKAGE_PATH}/include") + + set(V8_DIST + "${V8_REDIST_PACKAGE_PATH}/lib/Release/icudtl.dat" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_icu_icui18n.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_abseil-cpp_absl.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/icuuc.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libbase.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/v8_libplatform.dll" + "${V8_REDIST_PACKAGE_PATH}/lib/Release/third_party_zlib.dll") + + # only 1 imported location per library -> Adding 1 library per file + foreach(V8FILE ${V8_DIST}) + get_filename_component(V8FILE_NAME "${V8FILE}" NAME_WE) + add_library("v8::${V8FILE_NAME}" SHARED IMPORTED) + set_target_properties("v8::${V8FILE_NAME}" PROPERTIES IMPORTED_IMPLIB "${V8_PACKAGE_PATH}/lib/Release/v8_libbase.dll.lib") + set_target_properties("v8::${V8FILE_NAME}" PROPERTIES IMPORTED_LOCATION ${V8FILE}) + endforeach() + + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} + v8 + v8inspector + llhttp + v8::icudtl + v8::third_party_icu_icui18n + v8::icuuc + v8::v8 + v8::v8_libbase + v8::v8_libplatform + v8::third_party_zlib) + + if(CPU_ARCH STREQUAL "x64") + # Enable V8 Pointer Compression + # https://v8.dev/blog/pointer-compression + # https://stackoverflow.com/q/62921373 + set(NAPI_DEFINITIONS PUBLIC V8_COMPRESS_POINTERS) + endif() endif() endif() -add_executable(TestInstall ${LOCAL_SCRIPTS} ${NPM_SCRIPTS} ${SOURCES}) +add_executable(TestInstall ${LOCAL_SCRIPTS} ${SOURCES}) set(INSTALL_LIBS_DIR "${BINARY_DIR}/install/lib") target_include_directories(TestInstall PRIVATE "${BINARY_DIR}/install/include") +if(V8_INCLUDE_DIR) + target_include_directories(TestInstall PRIVATE "${V8_INCLUDE_DIR}") +endif() target_link_directories(TestInstall PRIVATE ${INSTALL_LIBS_DIR} ${V8JSI_LIB_PATH_RELEASE}) if(ANDROID OR IOS) diff --git a/Plugins/NativeEngine/Source/NativeEngine.cpp b/Plugins/NativeEngine/Source/NativeEngine.cpp index f933dc91c..b443db117 100644 --- a/Plugins/NativeEngine/Source/NativeEngine.cpp +++ b/Plugins/NativeEngine/Source/NativeEngine.cpp @@ -728,8 +728,6 @@ namespace Babylon InstanceMethod("populateFrameStats", &NativeEngine::PopulateFrameStats), - // REVIEW: Should this be here if only used by ValidationTest? - InstanceMethod("getFrameBufferData", &NativeEngine::GetFrameBufferData), InstanceMethod("setDeviceLostCallback", &NativeEngine::SetRenderResetCallback), }); @@ -2188,20 +2186,6 @@ namespace Babylon }); } - void NativeEngine::GetFrameBufferData(const Napi::CallbackInfo& info) - { - const auto callback{info[0].As()}; - - auto callbackPtr{std::make_shared(Napi::Persistent(callback))}; - m_deviceContext.RequestScreenShot([this, callbackPtr{std::move(callbackPtr)}](std::vector array) { - m_runtime.Dispatch([callbackPtr{std::move(callbackPtr)}, array{std::move(array)}](Napi::Env env) { - auto arrayBuffer{Napi::ArrayBuffer::New(env, const_cast(array.data()), array.size())}; - auto typedArray{Napi::Uint8Array::New(env, array.size(), arrayBuffer, 0)}; - callbackPtr->Value().Call({typedArray}); - }); - }); - } - void NativeEngine::SetStencil(NativeDataStream::Reader& data) { const uint32_t writeMask{data.ReadUint32()}; diff --git a/Plugins/NativeEngine/Source/NativeEngine.h b/Plugins/NativeEngine/Source/NativeEngine.h index 6b7690149..2eeecf5df 100644 --- a/Plugins/NativeEngine/Source/NativeEngine.h +++ b/Plugins/NativeEngine/Source/NativeEngine.h @@ -11,7 +11,6 @@ #include #include #include -#include #include diff --git a/Plugins/TestUtils/Source/TestUtils.cpp b/Plugins/TestUtils/Source/TestUtils.cpp index 7ec3ad500..2ef382ccd 100644 --- a/Plugins/TestUtils/Source/TestUtils.cpp +++ b/Plugins/TestUtils/Source/TestUtils.cpp @@ -71,4 +71,18 @@ namespace Babylon::Plugins::Internal return Napi::Value::From(info.Env(), data); } + + void TestUtils::GetFrameBufferData(const Napi::CallbackInfo& info) + { + const auto callback{ info[0].As() }; + + auto callbackPtr{ std::make_shared(Napi::Persistent(callback)) }; + m_deviceContext.RequestScreenShot([this, callbackPtr{ std::move(callbackPtr) }](std::vector array) { + m_runtime.Dispatch([callbackPtr{ std::move(callbackPtr) }, array{ std::move(array) }](Napi::Env env) { + auto arrayBuffer{ Napi::ArrayBuffer::New(env, const_cast(array.data()), array.size()) }; + auto typedArray{ Napi::Uint8Array::New(env, array.size(), arrayBuffer, 0) }; + callbackPtr->Value().Call({ typedArray }); + }); + }); + } } diff --git a/Plugins/TestUtils/Source/TestUtils.h b/Plugins/TestUtils/Source/TestUtils.h index 8b0eeb49e..d3e625e16 100644 --- a/Plugins/TestUtils/Source/TestUtils.h +++ b/Plugins/TestUtils/Source/TestUtils.h @@ -7,6 +7,8 @@ #include #include +#include +#include namespace Babylon::Plugins::Internal { @@ -36,12 +38,20 @@ namespace Babylon::Plugins::Internal ParentT::InstanceMethod("decodeImage", &TestUtils::DecodeImage), ParentT::InstanceMethod("getImageData", &TestUtils::GetImageData), ParentT::InstanceMethod("getOutputDirectory", &TestUtils::GetOutputDirectory), + ParentT::InstanceMethod("getFrameBufferData", &TestUtils::GetFrameBufferData), }); env.Global().Set(JS_INSTANCE_NAME, func.New({})); } - explicit TestUtils(const Napi::CallbackInfo& info) + TestUtils(const Napi::CallbackInfo& info) + : TestUtils(info, JsRuntime::GetFromJavaScript(info.Env())) + { + } + + explicit TestUtils(const Napi::CallbackInfo& info, JsRuntime& runtime) : ParentT{info} + , m_runtime{runtime} + , m_deviceContext{ Graphics::DeviceContext::GetFromJavaScript(info.Env()) } { } @@ -59,6 +69,10 @@ namespace Babylon::Plugins::Internal void WritePNG(const Napi::CallbackInfo& info); Napi::Value DecodeImage(const Napi::CallbackInfo& info); Napi::Value GetImageData(const Napi::CallbackInfo& info); + void GetFrameBufferData(const Napi::CallbackInfo& info); + + JsRuntime& m_runtime; + Graphics::DeviceContext& m_deviceContext; struct Image { diff --git a/azure-pipelines.yml b/azure-pipelines.yml index a92d48d65..2e8971a21 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -8,7 +8,7 @@ variables: - name: CMAKE_VERSION value: 3.31.6 - name: NDK_VERSION - value: 25.2.9519653 + value: 28.2.13676358 - name: UNITY_BUILD value: true - name: XCODE_VERSION @@ -141,11 +141,11 @@ jobs: - template: .github/jobs/test_install_macos.yml parameters: name: MacOS_Installation - vmImage: 'macOS-14' + vmImage: 'macOS-latest' - template: .github/jobs/test_install_ios.yml parameters: name: iOS_Installation - vmImage: 'macOS-14' + vmImage: 'macOS-latest' deploymentTarget: 17.2 # These Android tests are unstable on the CI emulator. Disabled until a more reliable solution is found.