From b994e05fc022ae643e73358136d58ee02178588d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Thu, 22 Aug 2024 15:15:51 +0200 Subject: [PATCH 1/6] chore: sync bgfx and bump ios-cmake --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 8131f7721..21df3de3b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ FetchContent_Declare(base-n GIT_TAG 7573e77c0b9b0e8a5fb63d96dbde212c921993b4) FetchContent_Declare(bgfx.cmake GIT_REPOSITORY https://github.com/BabylonJS/bgfx.cmake.git - GIT_TAG 17e2f84510dbb69c87a02b08fb11cecb2c4afc9b) + GIT_TAG a1582009254156a0396d600265d5611bc67e85fa) FetchContent_Declare(CMakeExtensions GIT_REPOSITORY https://github.com/BabylonJS/CMakeExtensions.git GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) From a8a453cd6eb80daf5b6dcdb68b75f509a3f6c982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Thu, 9 May 2024 15:05:48 +0200 Subject: [PATCH 2/6] feat: add visionOS support --- Apps/CMakeLists.txt | 2 +- Apps/Playground/CMakeLists.txt | 45 ++++++- Apps/Playground/visionOS/App.swift | 100 ++++++++++++++++ Apps/Playground/visionOS/Info.plist | 33 ++++++ Apps/Playground/visionOS/LibNativeBridge.cpp | 110 ++++++++++++++++++ Apps/Playground/visionOS/LibNativeBridge.hpp | 25 ++++ BUILDING.md | 38 ++++++ CMakeLists.txt | 12 ++ .../visionOS/Babylon/Graphics/Platform.h | 9 ++ .../Include/Shared/Babylon/Graphics/Device.h | 8 ++ Core/Graphics/Source/DeviceImpl.cpp | 1 + Core/Graphics/Source/DeviceImpl_visionOS.mm | 20 ++++ Dependencies/CMakeLists.txt | 6 +- Dependencies/xr/CMakeLists.txt | 17 ++- .../ARKit_visionOS/Include/IXrContextARKit.h | 10 ++ Dependencies/xr/Source/ARKit_visionOS/XR.mm | 15 +++ Plugins/CMakeLists.txt | 2 +- 17 files changed, 443 insertions(+), 10 deletions(-) create mode 100644 Apps/Playground/visionOS/App.swift create mode 100644 Apps/Playground/visionOS/Info.plist create mode 100644 Apps/Playground/visionOS/LibNativeBridge.cpp create mode 100644 Apps/Playground/visionOS/LibNativeBridge.hpp create mode 100644 Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h create mode 100644 Core/Graphics/Source/DeviceImpl_visionOS.mm create mode 100644 Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h create mode 100644 Dependencies/xr/Source/ARKit_visionOS/XR.mm diff --git a/Apps/CMakeLists.txt b/Apps/CMakeLists.txt index 0e7ade406..d4013e0e7 100644 --- a/Apps/CMakeLists.txt +++ b/Apps/CMakeLists.txt @@ -2,7 +2,7 @@ if(NOT ANDROID) add_subdirectory(Playground) endif() -if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID)) +if((WIN32 AND NOT WINDOWS_STORE) OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID)) add_subdirectory(UnitTests) endif() diff --git a/Apps/Playground/CMakeLists.txt b/Apps/Playground/CMakeLists.txt index 26cb8324e..57d87cc6c 100644 --- a/Apps/Playground/CMakeLists.txt +++ b/Apps/Playground/CMakeLists.txt @@ -35,9 +35,24 @@ if(APPLE) "iOS/LibNativeBridge.mm") set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) + elseif(VISIONOS) + set(PLIST_FILE + "${CMAKE_CURRENT_LIST_DIR}/visionOS/Info.plist") + set(RESOURCE_FILES ${SCRIPTS}) + set(SOURCES + ${SOURCES} + "visionOS/App.swift" + "visionOS/LibNativeBridge.cpp" + "visionOS/LibNativeBridge.hpp" + ) + set(ADDITIONAL_LIBRARIES PRIVATE NativeXr) + set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") + set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") else() set(PLIST_FILE "${CMAKE_CURRENT_LIST_DIR}/macOS/Info.plist") set(STORYBOARD "${CMAKE_CURRENT_LIST_DIR}/macOS/Base.lproj/Main.storyboard") + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) set(RESOURCE_FILES ${STORYBOARD}) set(SOURCES ${SOURCES} @@ -49,9 +64,7 @@ if(APPLE) set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "Resources/ReferenceImages") endif() - set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} - PRIVATE ${JAVASCRIPTCORE_LIBRARY} - PRIVATE NativeCamera) + set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE ${JAVASCRIPTCORE_LIBRARY}) set(RESOURCE_FILES ${STORYBOARD}) elseif(UNIX) @@ -163,6 +176,30 @@ if(APPLE) set(CMAKE_Swift_COMPILER_FORCED TRUE) set(CMAKE_Swift_LANGUAGE_VERSION 4.0) enable_language(Swift) + elseif(VISIONOS) + set_target_properties(Playground PROPERTIES + MACOSX_BUNDLE true + MACOSX_BUNDLE_INFO_PLIST "${PLIST_FILE}" + XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES + RESOURCE "${RESOURCE_FILES}" + + XCODE_ATTRIBUTE_XROS_DEPLOYMENT_TARGET ${DEPLOYMENT_TARGET} + XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.BabylonNative.Playground.visionOS" + + XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/visionOS/LibNativeBridge.hpp" + XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES + XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx" + + # CMake seems to add a custom flag "-Wno-unknown-pragmas" to the Swift compiler. That flag is used for Clang, + # So we need to make sure we override it with nothing here in order to compile Swift. + XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") + + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 5.0) + enable_language(Swift) else() target_link_libraries(Playground PUBLIC "-framework MetalKit") @@ -209,3 +246,5 @@ source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SCRIPTS}) source_group(TREE ${CMAKE_CURRENT_SOURCE_DIR} FILES ${SOURCES}) set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT Playground) +set_property(TARGET Playground PROPERTY XCODE_GENERATE_SCHEME YES) +set_property(TARGET Playground PROPERTY XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED YES) diff --git a/Apps/Playground/visionOS/App.swift b/Apps/Playground/visionOS/App.swift new file mode 100644 index 000000000..d39edfe99 --- /dev/null +++ b/Apps/Playground/visionOS/App.swift @@ -0,0 +1,100 @@ +import SwiftUI +import CompositorServices + +struct ContentStageConfiguration: CompositorLayerConfiguration { + func makeConfiguration(capabilities: LayerRenderer.Capabilities, configuration: inout LayerRenderer.Configuration) { + configuration.depthFormat = .depth32Float + configuration.colorFormat = .bgra8Unorm_srgb + + let foveationEnabled = capabilities.supportsFoveation + configuration.isFoveationEnabled = foveationEnabled + + let options: LayerRenderer.Capabilities.SupportedLayoutsOptions = foveationEnabled ? [.foveationEnabled] : [] + let supportedLayouts = capabilities.supportedLayouts(options: options) + + configuration.layout = supportedLayouts.contains(.layered) ? .layered : .dedicated + } +} + +class Renderer { + let layerRenderer: LayerRenderer + var libNativeBridge: LibNativeBridge + + init(_ layerRenderer: LayerRenderer) { + self.layerRenderer = layerRenderer + self.libNativeBridge = LibNativeBridge(layerRenderer) + } + + func startRenderLoop() { + let renderThread = Thread { + self.renderLoop() + } + renderThread.name = "Render Thread" + renderThread.start() + } + + + func renderLoop() { + while true { + if layerRenderer.state == .invalidated { + print("Layer is invalidated") + + libNativeBridge.shutdown() + return + } else if layerRenderer.state == .paused { + layerRenderer.waitUntilRunning() + continue + } else { + autoreleasepool { + libNativeBridge.initialize() + libNativeBridge.render() + } + } + } + } +} + + +@main +struct ExampleApp: App { + @State private var showImmersiveSpace = false + @State private var immersiveSpaceIsShown = false + + @Environment(\.openImmersiveSpace) var openImmersiveSpace + @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace + + var body: some Scene { + WindowGroup { + VStack { + Toggle("Show Immersive Space", isOn: $showImmersiveSpace) + .toggleStyle(.button) + .padding(.top, 50) + } + .onChange(of: showImmersiveSpace) { _, newValue in + Task { + if newValue { + switch await openImmersiveSpace(id: "ImmersiveSpace") { + case .opened: + immersiveSpaceIsShown = true + case .error, .userCancelled: + fallthrough + @unknown default: + immersiveSpaceIsShown = false + showImmersiveSpace = false + } + } else if immersiveSpaceIsShown { + await dismissImmersiveSpace() + immersiveSpaceIsShown = false + } + } + } + + } + ImmersiveSpace(id: "ImmersiveSpace") { + CompositorLayer(configuration: ContentStageConfiguration()) { layerRenderer in + let renderer = Renderer(layerRenderer) + renderer.startRenderLoop() + } + }.immersionStyle(selection: .constant(.mixed), in: .mixed, .full) + } +} diff --git a/Apps/Playground/visionOS/Info.plist b/Apps/Playground/visionOS/Info.plist new file mode 100644 index 000000000..1f9bad276 --- /dev/null +++ b/Apps/Playground/visionOS/Info.plist @@ -0,0 +1,33 @@ + + + + + NSPhotoLibraryAddUsageDescription + Need photo library permission for debug code to save photo captures + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + APPL + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + UIApplicationSceneManifest + + UIApplicationPreferredDefaultSceneSessionRole + UIWindowSceneSessionRoleApplication + UIApplicationSupportsMultipleScenes + + UISceneConfigurations + + + + diff --git a/Apps/Playground/visionOS/LibNativeBridge.cpp b/Apps/Playground/visionOS/LibNativeBridge.cpp new file mode 100644 index 000000000..77ab114cd --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.cpp @@ -0,0 +1,110 @@ +#import "LibNativeBridge.hpp" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +std::optional device{}; +std::optional update{}; +std::optional runtime{}; +std::optional nativeCanvas{}; +std::optional nativeXr{}; +Babylon::Plugins::NativeInput* nativeInput{}; +bool isXrActive{}; + + +bool LibNativeBridge::initialize() { + if (m_initialized) { + return true; + } + + Babylon::Graphics::Configuration graphicsConfig{}; + graphicsConfig.Window = m_layerRenderer; + // Pass in visionOS default widht and height. +#if TARGET_OS_SIMULATOR + graphicsConfig.Width = static_cast(2732); + graphicsConfig.Height = static_cast(2048); +#else + graphicsConfig.Width = static_cast(1920); + graphicsConfig.Height = static_cast(1824); +#endif + + device.emplace(graphicsConfig); + update.emplace(device->GetUpdate("update")); + + device->StartRenderingCurrentFrame(); + update->Start(); + + runtime.emplace(); + + runtime->Dispatch([](Napi::Env env) + { + device->AddToJavaScript(env); + + Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { + NSLog(@"%s", message); + }); + + nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env)); + + Babylon::Polyfills::Window::Initialize(env); + + Babylon::Polyfills::XMLHttpRequest::Initialize(env); + + Babylon::Plugins::NativeEngine::Initialize(env); + + Babylon::Plugins::NativeOptimizations::Initialize(env); +// nativeXr.emplace(Babylon::Plugins::NativeXr::Initialize(env)); +// nativeXr->UpdateWindow((__bridge void*)m_layerRenderer); + + nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); + }); + + Babylon::ScriptLoader loader{ *runtime }; + loader.LoadScript("app:///Scripts/ammo.js"); + loader.LoadScript("app:///Scripts/recast.js"); + loader.LoadScript("app:///Scripts/babylon.max.js"); + loader.LoadScript("app:///Scripts/babylonjs.loaders.js"); + loader.LoadScript("app:///Scripts/babylonjs.materials.js"); + loader.LoadScript("app:///Scripts/babylon.gui.js"); + loader.LoadScript("app:///Scripts/experience.js"); + m_initialized = true; + + return true; +} + +void LibNativeBridge::render() { + if (device && m_initialized) + { + update->Finish(); + device->FinishRenderingCurrentFrame(); + device->StartRenderingCurrentFrame(); + update->Start(); + } +} + +void LibNativeBridge::shutdown() { + if (!m_initialized) { + return; + } + + if (device) + { + update->Finish(); + device->FinishRenderingCurrentFrame(); + } + + nativeInput = {}; + nativeCanvas.reset(); + runtime.reset(); + update.reset(); + device.reset(); + m_initialized = false; +} diff --git a/Apps/Playground/visionOS/LibNativeBridge.hpp b/Apps/Playground/visionOS/LibNativeBridge.hpp new file mode 100644 index 000000000..c1d544175 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.hpp @@ -0,0 +1,25 @@ +#ifndef BgfxAdapter_hpp +#define BgfxAdapter_hpp + +#include +#include + +class LibNativeBridge { +private: + bool m_initialized = false; + cp_layer_renderer_t m_layerRenderer = NULL; + +public: + LibNativeBridge(cp_layer_renderer_t layerRenderer) : m_layerRenderer(layerRenderer) { + } + + ~LibNativeBridge() { + shutdown(); + } + + bool initialize(void); + void shutdown(void); + void render(void); +}; + +#endif /* BgfxAdapter_hpp */ diff --git a/BUILDING.md b/BUILDING.md index b9840ed6f..b086e7498 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -192,6 +192,44 @@ demo app, click on the project selector and find `Playground` in the list of pos selections. The `Play` button will subsequently allow you to build, run, and debug the selected Babylon Native demo app. +## **Building on macOS, Targeting visionOS** + +_Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ + +**Required Tools:** [Xcode 15](https://developer.apple.com/xcode/) or newer, +[Python 3.0](https://www.python.org/) or newer (required by dependencies) + +For macOS development, CMake will generate a Makefile by default. It may be possible +to build Babylon Native for macOS using this approach, but only the Xcode method is +supported at present. To generate an Xcode project using CMake, you must specify the +correct build system generator for CMake to use. Additionally, you must tell CMake +what toolchain to use, which provides additional information about how to generate an +visionOS Xcode project correctly. Run the following command from the repository root: + +``` +cmake -B build/visionOS -G Xcode -D VISIONOS=ON +``` + +To enable bitcode support, add this option to the cmake command line parameters: + +``` +-D ENABLE_BITCODE=ON +``` + +CMake will generate a new `BabylonNative.xcodeproj` file in the specified build folder. +Open the project by double-clicking on it in Finder or by entering the following command: + +``` +open build/visionOS/BabylonNative.xcodeproj +``` + +To select which project to build with Xcode, select the correct project name in the +menu to the right of the greyed-out `Stop` button adjacent to the `Play` button in +the top-left corner of the Xcode window. For example, to build and run the Playground +demo app, click on the project selector and find `Playground` in the list of possible +selections. The `Play` button will subsequently allow you to build, run, and debug +the selected Babylon Native demo app. + ## **Building on Windows, Targeting Android** _Follow the steps from [All Development Platforms](#all-development-platforms) before proceeding._ diff --git a/CMakeLists.txt b/CMakeLists.txt index 21df3de3b..5e166cdde 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,6 +51,15 @@ FetchContent_Declare(SPIRV-Cross FetchContent_MakeAvailable(CMakeExtensions) + +if(VISIONOS) + FetchContent_MakeAvailable_With_Message(ios-cmake) + set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") + set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") + set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") + set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") +endif() + if(IOS) FetchContent_MakeAvailable_With_Message(ios-cmake) set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") @@ -59,6 +68,7 @@ if(IOS) set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") endif() + project(BabylonNative) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -98,6 +108,8 @@ if(ANDROID) set(BABYLON_NATIVE_PLATFORM "Android") elseif(IOS) set(BABYLON_NATIVE_PLATFORM "iOS") +elseif (VISIONOS) + set(BABYLON_NATIVE_PLATFORM "visionOS") elseif(APPLE) set(BABYLON_NATIVE_PLATFORM "macOS") elseif(WINDOWS_STORE) diff --git a/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h new file mode 100644 index 000000000..2592b6201 --- /dev/null +++ b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h @@ -0,0 +1,9 @@ +#pragma once + +#import + + +namespace Babylon::Graphics +{ + using WindowT = cp_layer_renderer_t; +} diff --git a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h index 9a42719c1..cc0de0ef9 100644 --- a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h +++ b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h @@ -4,6 +4,10 @@ #include #include +#if TARGET_OS_VISION +#include +#endif + #include #include @@ -28,6 +32,10 @@ namespace Babylon::Graphics // When enabled, back buffer will be premultiplied with alpha value. bool AlphaPremultiplied{}; + +#if TARGET_OS_VISION + ar_world_tracking_provider_t WorldTracking; +#endif }; class Device; diff --git a/Core/Graphics/Source/DeviceImpl.cpp b/Core/Graphics/Source/DeviceImpl.cpp index 1a21f3903..c9f6d6e3f 100644 --- a/Core/Graphics/Source/DeviceImpl.cpp +++ b/Core/Graphics/Source/DeviceImpl.cpp @@ -44,6 +44,7 @@ namespace Babylon::Graphics init.callback = &m_bgfxCallback; init.platformData.context = config.Device; + UpdateWindow(config.Window); UpdateSize(config.Width, config.Height); UpdateMSAA(config.MSAASamples); diff --git a/Core/Graphics/Source/DeviceImpl_visionOS.mm b/Core/Graphics/Source/DeviceImpl_visionOS.mm new file mode 100644 index 000000000..2f2fdae5f --- /dev/null +++ b/Core/Graphics/Source/DeviceImpl_visionOS.mm @@ -0,0 +1,20 @@ +#include +#include "DeviceImpl.h" + +namespace Babylon::Graphics +{ + void DeviceImpl::ConfigureBgfxPlatformData(bgfx::PlatformData& pd, WindowT window) + { + pd.nwh = window; + } + + void DeviceImpl::ConfigureBgfxRenderType(bgfx::PlatformData& /*pd*/, bgfx::RendererType::Enum& /*renderType*/) + { + } + + float DeviceImpl::GetDevicePixelRatio(WindowT window) + { + BX_UNUSED(window); + return 2.0; + } +} diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 47cee4242..27a8ebed2 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -106,7 +106,7 @@ set_property(TARGET SPIRV PROPERTY FOLDER Dependencies/glslang) # -------------------------------------------------- # googletest # -------------------------------------------------- -if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS) OR (UNIX AND NOT ANDROID))) +if(BABYLON_NATIVE_BUILD_APPS AND (WIN32 OR (APPLE AND NOT IOS AND NOT VISIONOS) OR (UNIX AND NOT ANDROID))) if(WIN32) # For Windows: Prevent overriding the parent project's compiler/linker settings # Default build type for my test projects are /MDd (MultiThreaded DLL) but GTests default to /MTd (MultiTreaded) @@ -186,8 +186,8 @@ disable_warnings(MachineIndependent) # -------------------------------------------------- # xr # -------------------------------------------------- -# Currently supported on Windows via OpenXR, Android via ARCore, and iOS via ARKit. -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) +# Currently supported on Windows via OpenXR, Android via ARCore, iOS and visionOS via ARKit. +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) add_subdirectory(xr) set_property(TARGET xr PROPERTY FOLDER Dependencies/xr) warnings_as_errors(xr) diff --git a/Dependencies/xr/CMakeLists.txt b/Dependencies/xr/CMakeLists.txt index 593b5043d..66d1fafae 100644 --- a/Dependencies/xr/CMakeLists.txt +++ b/Dependencies/xr/CMakeLists.txt @@ -10,7 +10,7 @@ FetchContent_Declare(CMakeExtensions GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) FetchContent_Declare(ios-cmake GIT_REPOSITORY https://github.com/leetal/ios-cmake.git - GIT_TAG 4.4.1) + GIT_TAG a52c591bc9056f3ae20a461d16fdd73ab4325be7) # -------------------------------------------------- FetchContent_MakeAvailable(CMakeExtensions) @@ -22,6 +22,15 @@ if(IOS) set(DEPLOYMENT_TARGET "13" CACHE STRING "") endif() +if(VISIONOS) + FetchContent_MakeAvailable_With_Message(ios-cmake) + set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") + set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") + set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") + set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") +endif() + + project(xr) # Avoid picking up system installed jsoncpp in favor of source distributed with openxr_loader project @@ -47,6 +56,10 @@ elseif (IOS) set(SOURCES ${SOURCES} "Source/ARKit/Include/IXrContextARKit.h" "Source/ARKit/XR.mm") +elseif (VISIONOS) + set(SOURCES ${SOURCES} + "Source/ARKit_visionOS/Include/IXrContextARKit.h" + "Source/ARKit_visionOS/XR.mm") else() set(SOURCES ${SOURCES} "Source/OpenXR/XR.cpp") @@ -91,7 +104,7 @@ if (ANDROID) set_target_properties(glm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${arcore-android-sdk_SOURCE_DIR}/libraries/glm) target_link_libraries(xr PRIVATE glm arcore AndroidExtensions) -elseif (IOS) +elseif (IOS OR VISIONOS) target_link_libraries(xr PRIVATE "-framework ARKit") else() if(WIN32) diff --git a/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h b/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h new file mode 100644 index 000000000..a3d2ffecd --- /dev/null +++ b/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h @@ -0,0 +1,10 @@ + +#pragma once + +#include + +typedef struct IXrContextARKit +{ + virtual bool IsInitialized() const = 0; + virtual ar_session_t XrSession() const = 0; +} IXrContextARKit; diff --git a/Dependencies/xr/Source/ARKit_visionOS/XR.mm b/Dependencies/xr/Source/ARKit_visionOS/XR.mm new file mode 100644 index 000000000..b442beb45 --- /dev/null +++ b/Dependencies/xr/Source/ARKit_visionOS/XR.mm @@ -0,0 +1,15 @@ +#import +#import + +#import +#import +#import + +#import "Include/IXrContextARKit.h" + + +// TODO: Implement the visionOS ARKit api +namespace xr { +struct System::Session::Impl { +}; +} diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index 89d8982b2..0f216f16c 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -30,6 +30,6 @@ if(BABYLON_NATIVE_PLUGIN_TESTUTILS) add_subdirectory(TestUtils) endif() -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) add_subdirectory(NativeXr) endif() From 3d0041e535f55b56ce50c793301554b568ce5eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Wed, 14 Aug 2024 12:29:29 +0200 Subject: [PATCH 3/6] feat: move to flat rendering --- .../AppleShared/GestureRecognizer.swift | 58 ++++++ Apps/Playground/CMakeLists.txt | 17 +- Apps/Playground/iOS/ViewController.swift | 57 ------ Apps/Playground/visionOS/App.swift | 174 ++++++++++-------- Apps/Playground/visionOS/LibNativeBridge.cpp | 110 ----------- Apps/Playground/visionOS/LibNativeBridge.h | 23 +++ Apps/Playground/visionOS/LibNativeBridge.hpp | 25 --- Apps/Playground/visionOS/LibNativeBridge.mm | 145 +++++++++++++++ .../visionOS/Babylon/Graphics/Platform.h | 5 +- .../Include/Shared/Babylon/Graphics/Device.h | 8 - Core/Graphics/Source/DeviceImpl.cpp | 1 - Core/Graphics/Source/DeviceImpl_visionOS.mm | 5 +- Dependencies/CMakeLists.txt | 4 +- Dependencies/xr/CMakeLists.txt | 17 +- .../ARKit_visionOS/Include/IXrContextARKit.h | 10 - Dependencies/xr/Source/ARKit_visionOS/XR.mm | 15 -- Plugins/CMakeLists.txt | 2 +- 17 files changed, 340 insertions(+), 336 deletions(-) create mode 100644 Apps/Playground/AppleShared/GestureRecognizer.swift delete mode 100644 Apps/Playground/visionOS/LibNativeBridge.cpp create mode 100644 Apps/Playground/visionOS/LibNativeBridge.h delete mode 100644 Apps/Playground/visionOS/LibNativeBridge.hpp create mode 100644 Apps/Playground/visionOS/LibNativeBridge.mm delete mode 100644 Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h delete mode 100644 Dependencies/xr/Source/ARKit_visionOS/XR.mm diff --git a/Apps/Playground/AppleShared/GestureRecognizer.swift b/Apps/Playground/AppleShared/GestureRecognizer.swift new file mode 100644 index 000000000..f071aa7ad --- /dev/null +++ b/Apps/Playground/AppleShared/GestureRecognizer.swift @@ -0,0 +1,58 @@ +import UIKit + +/** +* A very simple gesture recognizer. All that it does is to emulate the functionality found in other platforms +*/ +class UIBabylonGestureRecognizer: UIGestureRecognizer { + // Callback for touch down events + private let _onTouchDown: (Int32, Int32, Int32)->Void + // Callback for touch movement events + private let _onTouchMove: (Int32, Int32, Int32)->Void + // Callback for touch up events + private let _onTouchUp: (Int32, Int32, Int32)->Void + // Table to track hashes of active touches + private var _activeTouchIds: Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] + + public init(target: Any?, onTouchDown: @escaping(Int32, Int32, Int32)->Void, onTouchMove: @escaping(Int32, Int32, Int32)->Void, onTouchUp: @escaping(Int32, Int32, Int32)->Void) { + _onTouchDown = onTouchDown + _onTouchMove = onTouchMove + _onTouchUp = onTouchUp + + super.init(target: target, action: nil) + } + + override func touchesBegan(_ touches: Set, with event: UIEvent) { + super.touchesBegan(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: -1) else { continue } + _activeTouchIds[deviceSlot] = touch.hash + let loc = touch.location(in: view) + + _onTouchDown(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + } + } + + override func touchesMoved(_ touches: Set, with event: UIEvent) { + super.touchesMoved(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } + let loc = touch.location(in: view) + + _onTouchMove(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + } + } + + override func touchesEnded(_ touches: Set, with event: UIEvent) { + super.touchesEnded(touches, with: event) + + for touch in touches { + guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } + let loc = touch.location(in: view) + + _onTouchUp(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) + _activeTouchIds[deviceSlot] = -1 + } + } +} diff --git a/Apps/Playground/CMakeLists.txt b/Apps/Playground/CMakeLists.txt index 57d87cc6c..1482f6c26 100644 --- a/Apps/Playground/CMakeLists.txt +++ b/Apps/Playground/CMakeLists.txt @@ -32,7 +32,8 @@ if(APPLE) "iOS/AppDelegate.swift" "iOS/ViewController.swift" "iOS/LibNativeBridge.h" - "iOS/LibNativeBridge.mm") + "iOS/LibNativeBridge.mm" + "AppleShared/GestureRecognizer.swift") set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE NativeCamera) @@ -43,10 +44,9 @@ if(APPLE) set(SOURCES ${SOURCES} "visionOS/App.swift" - "visionOS/LibNativeBridge.cpp" - "visionOS/LibNativeBridge.hpp" - ) - set(ADDITIONAL_LIBRARIES PRIVATE NativeXr) + "visionOS/LibNativeBridge.mm" + "visionOS/LibNativeBridge.h" + "AppleShared/GestureRecognizer.swift") set_source_files_properties(${SCRIPTS} ${BABYLON_SCRIPTS} ${DEPENDENCIES} PROPERTIES MACOSX_PACKAGE_LOCATION "Scripts") set_source_files_properties(${REFERENCE_IMAGES} PROPERTIES MACOSX_PACKAGE_LOCATION "ReferenceImages") else() @@ -67,6 +67,9 @@ if(APPLE) set(ADDITIONAL_LIBRARIES ${ADDITIONAL_LIBRARIES} PRIVATE ${JAVASCRIPTCORE_LIBRARY}) set(RESOURCE_FILES ${STORYBOARD}) + # Remove -Wall and -Werror from the debug flags to make simulators work. + string(REPLACE "-Wall" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") + string(REPLACE "-Werror" "" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}") elseif(UNIX) set(SOURCES ${SOURCES} @@ -166,6 +169,7 @@ if(APPLE) XCODE_ATTRIBUTE_SWIFT_VERSION "4.0" XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/iOS/LibNativeBridge.h" XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks" XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES # CMake seems to add a custom flag "-Wno-unknown-pragmas" to the Swift compiler. That flag is used for Clang, @@ -187,8 +191,9 @@ if(APPLE) XCODE_ATTRIBUTE_PRODUCT_BUNDLE_IDENTIFIER "com.BabylonNative.Playground.visionOS" XCODE_ATTRIBUTE_SWIFT_VERSION "5.0" - XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/visionOS/LibNativeBridge.hpp" + XCODE_ATTRIBUTE_SWIFT_OBJC_BRIDGING_HEADER "${CMAKE_CURRENT_LIST_DIR}/visionOS/LibNativeBridge.h" XCODE_ATTRIBUTE_LD_RUNPATH_SEARCH_PATHS "@executable_path/Frameworks" + XCODE_ATTRIBUTE_FRAMEWORK_SEARCH_PATHS "$(inherited) $(SDKROOT)$(SYSTEM_LIBRARY_DIR)/Frameworks" XCODE_ATTRIBUTE_ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES YES XCODE_ATTRIBUTE_SWIFT_OBJC_INTEROP_MODE "objcxx" diff --git a/Apps/Playground/iOS/ViewController.swift b/Apps/Playground/iOS/ViewController.swift index d0189e081..2d44facdc 100644 --- a/Apps/Playground/iOS/ViewController.swift +++ b/Apps/Playground/iOS/ViewController.swift @@ -1,63 +1,6 @@ import UIKit import MetalKit -/** - * A very simple gesture recognizer. All that it does is to emulate the functionality found in other platforms - */ -class UIBabylonGestureRecognizer: UIGestureRecognizer { - // Callback for touch down events - private let _onTouchDown: (Int32, Int32, Int32)->Void - // Callback for touch movement events - private let _onTouchMove: (Int32, Int32, Int32)->Void - // Callback for touch up events - private let _onTouchUp: (Int32, Int32, Int32)->Void - // Table to track hashes of active touches - private var _activeTouchIds: Array = [-1, -1, -1, -1, -1, -1, -1, -1, -1, -1] - - public init(target: Any?, onTouchDown: @escaping(Int32, Int32, Int32)->Void, onTouchMove: @escaping(Int32, Int32, Int32)->Void, onTouchUp: @escaping(Int32, Int32, Int32)->Void) { - _onTouchDown = onTouchDown - _onTouchMove = onTouchMove - _onTouchUp = onTouchUp - - super.init(target: target, action: nil) - } - - override func touchesBegan(_ touches: Set, with event: UIEvent) { - super.touchesBegan(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: -1) else { continue } - _activeTouchIds[deviceSlot] = touch.hash - let loc = touch.location(in: view) - - _onTouchDown(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - } - } - - override func touchesMoved(_ touches: Set, with event: UIEvent) { - super.touchesMoved(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } - let loc = touch.location(in: view) - - _onTouchMove(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - } - } - - override func touchesEnded(_ touches: Set, with event: UIEvent) { - super.touchesEnded(touches, with: event) - - for touch in touches { - guard let deviceSlot = _activeTouchIds.firstIndex(of: touch.hash) else { continue } - let loc = touch.location(in: view) - - _onTouchUp(Int32(deviceSlot), Int32(loc.x), Int32(loc.y)) - _activeTouchIds[deviceSlot] = -1 - } - } -} - class ViewController: UIViewController { var mtkView: MTKView! diff --git a/Apps/Playground/visionOS/App.swift b/Apps/Playground/visionOS/App.swift index d39edfe99..ed0f5c226 100644 --- a/Apps/Playground/visionOS/App.swift +++ b/Apps/Playground/visionOS/App.swift @@ -1,100 +1,112 @@ import SwiftUI -import CompositorServices -struct ContentStageConfiguration: CompositorLayerConfiguration { - func makeConfiguration(capabilities: LayerRenderer.Capabilities, configuration: inout LayerRenderer.Configuration) { - configuration.depthFormat = .depth32Float - configuration.colorFormat = .bgra8Unorm_srgb - - let foveationEnabled = capabilities.supportsFoveation - configuration.isFoveationEnabled = foveationEnabled - - let options: LayerRenderer.Capabilities.SupportedLayoutsOptions = foveationEnabled ? [.foveationEnabled] : [] - let supportedLayouts = capabilities.supportedLayouts(options: options) - - configuration.layout = supportedLayouts.contains(.layered) ? .layered : .dedicated +class Renderer { + static var shared = Renderer() + + var displayLink: CADisplayLink? = nil + var libNativeBridge: LibNativeBridge? = nil + + var metalView: UIView? { + didSet { + libNativeBridge = LibNativeBridge(metalLayer: metalView?.layer as? CAMetalLayer) + let scale = UITraitCollection.current.displayScale + libNativeBridge?.initialize(withWidth: Int((metalView?.bounds.width ?? 0) * scale), height: Int((metalView?.bounds.height ?? 0) * scale)) + self.displayLink = CADisplayLink(target: self, selector: #selector(self.renderMetalLoop)) + self.displayLink?.add(to: .main, forMode: .common) + } + } + + init() {} + + @objc func renderMetalLoop() { + libNativeBridge?.render() + } + + func drawableWillChangeSize(width: Int, height: Int) { + libNativeBridge?.drawableWillChangeSize(withWidth: Int(width), height: Int(height)) + } + + func setTouchMove(pointerId: Int32, x: Int32, y: Int32) { + libNativeBridge?.setTouchMoveWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) + } + + func setTouchDown(pointerId: Int32, x: Int32, y: Int32) { + libNativeBridge?.setTouchDownWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) + } + + func setTouchUp(pointerId: Int32, x: Int32, y: Int32) { + libNativeBridge?.setTouchUpWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) } } -class Renderer { - let layerRenderer: LayerRenderer - var libNativeBridge: LibNativeBridge - - init(_ layerRenderer: LayerRenderer) { - self.layerRenderer = layerRenderer - self.libNativeBridge = LibNativeBridge(layerRenderer) +class MetalView: UIView { + + override init(frame: CGRect) { + super.init(frame: frame) + self.backgroundColor = .clear } - - func startRenderLoop() { - let renderThread = Thread { - self.renderLoop() - } - renderThread.name = "Render Thread" - renderThread.start() + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") } - - - func renderLoop() { - while true { - if layerRenderer.state == .invalidated { - print("Layer is invalidated") - - libNativeBridge.shutdown() - return - } else if layerRenderer.state == .paused { - layerRenderer.waitUntilRunning() - continue - } else { - autoreleasepool { - libNativeBridge.initialize() - libNativeBridge.render() - } - } + + func setupMetalLayer() { + if Renderer.shared.metalView != nil { + return } + + self.addGestureRecognizer( + UIBabylonGestureRecognizer( + target: self, + onTouchDown: Renderer.shared.setTouchDown, + onTouchMove: Renderer.shared.setTouchMove, + onTouchUp: Renderer.shared.setTouchUp + ) + ) + metalLayer.pixelFormat = .bgra8Unorm + metalLayer.framebufferOnly = true + // Assign metalView to renderer + Renderer.shared.metalView = self + } + + var metalLayer: CAMetalLayer { + return layer as! CAMetalLayer + } + + override class var layerClass: AnyClass { + return CAMetalLayer.self + } + + override func layoutSubviews() { + super.layoutSubviews() + setupMetalLayer() + updateDrawableSize() + } + + private func updateDrawableSize() { + let scale = UITraitCollection.current.displayScale + Renderer.shared.drawableWillChangeSize(width: Int(bounds.width * scale), height: Int(bounds.height * scale)) + metalLayer.drawableSize = CGSize(width: bounds.width * scale, height: bounds.height * scale) } } +struct MetalViewRepresentable: UIViewRepresentable { + typealias UIViewType = MetalView + + func makeUIView(context: Context) -> MetalView { + MetalView(frame: .zero) + } + + func updateUIView(_ uiView: MetalView, context: Context) {} +} + @main struct ExampleApp: App { - @State private var showImmersiveSpace = false - @State private var immersiveSpaceIsShown = false - - @Environment(\.openImmersiveSpace) var openImmersiveSpace - @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace - var body: some Scene { WindowGroup { - VStack { - Toggle("Show Immersive Space", isOn: $showImmersiveSpace) - .toggleStyle(.button) - .padding(.top, 50) - } - .onChange(of: showImmersiveSpace) { _, newValue in - Task { - if newValue { - switch await openImmersiveSpace(id: "ImmersiveSpace") { - case .opened: - immersiveSpaceIsShown = true - case .error, .userCancelled: - fallthrough - @unknown default: - immersiveSpaceIsShown = false - showImmersiveSpace = false - } - } else if immersiveSpaceIsShown { - await dismissImmersiveSpace() - immersiveSpaceIsShown = false - } - } - } - + MetalViewRepresentable() + .frame(maxWidth: .infinity, maxHeight: .infinity) } - ImmersiveSpace(id: "ImmersiveSpace") { - CompositorLayer(configuration: ContentStageConfiguration()) { layerRenderer in - let renderer = Renderer(layerRenderer) - renderer.startRenderLoop() - } - }.immersionStyle(selection: .constant(.mixed), in: .mixed, .full) } } diff --git a/Apps/Playground/visionOS/LibNativeBridge.cpp b/Apps/Playground/visionOS/LibNativeBridge.cpp deleted file mode 100644 index 77ab114cd..000000000 --- a/Apps/Playground/visionOS/LibNativeBridge.cpp +++ /dev/null @@ -1,110 +0,0 @@ -#import "LibNativeBridge.hpp" -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import -#import - -std::optional device{}; -std::optional update{}; -std::optional runtime{}; -std::optional nativeCanvas{}; -std::optional nativeXr{}; -Babylon::Plugins::NativeInput* nativeInput{}; -bool isXrActive{}; - - -bool LibNativeBridge::initialize() { - if (m_initialized) { - return true; - } - - Babylon::Graphics::Configuration graphicsConfig{}; - graphicsConfig.Window = m_layerRenderer; - // Pass in visionOS default widht and height. -#if TARGET_OS_SIMULATOR - graphicsConfig.Width = static_cast(2732); - graphicsConfig.Height = static_cast(2048); -#else - graphicsConfig.Width = static_cast(1920); - graphicsConfig.Height = static_cast(1824); -#endif - - device.emplace(graphicsConfig); - update.emplace(device->GetUpdate("update")); - - device->StartRenderingCurrentFrame(); - update->Start(); - - runtime.emplace(); - - runtime->Dispatch([](Napi::Env env) - { - device->AddToJavaScript(env); - - Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { - NSLog(@"%s", message); - }); - - nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env)); - - Babylon::Polyfills::Window::Initialize(env); - - Babylon::Polyfills::XMLHttpRequest::Initialize(env); - - Babylon::Plugins::NativeEngine::Initialize(env); - - Babylon::Plugins::NativeOptimizations::Initialize(env); -// nativeXr.emplace(Babylon::Plugins::NativeXr::Initialize(env)); -// nativeXr->UpdateWindow((__bridge void*)m_layerRenderer); - - nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); - }); - - Babylon::ScriptLoader loader{ *runtime }; - loader.LoadScript("app:///Scripts/ammo.js"); - loader.LoadScript("app:///Scripts/recast.js"); - loader.LoadScript("app:///Scripts/babylon.max.js"); - loader.LoadScript("app:///Scripts/babylonjs.loaders.js"); - loader.LoadScript("app:///Scripts/babylonjs.materials.js"); - loader.LoadScript("app:///Scripts/babylon.gui.js"); - loader.LoadScript("app:///Scripts/experience.js"); - m_initialized = true; - - return true; -} - -void LibNativeBridge::render() { - if (device && m_initialized) - { - update->Finish(); - device->FinishRenderingCurrentFrame(); - device->StartRenderingCurrentFrame(); - update->Start(); - } -} - -void LibNativeBridge::shutdown() { - if (!m_initialized) { - return; - } - - if (device) - { - update->Finish(); - device->FinishRenderingCurrentFrame(); - } - - nativeInput = {}; - nativeCanvas.reset(); - runtime.reset(); - update.reset(); - device.reset(); - m_initialized = false; -} diff --git a/Apps/Playground/visionOS/LibNativeBridge.h b/Apps/Playground/visionOS/LibNativeBridge.h new file mode 100644 index 000000000..5f89a2588 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.h @@ -0,0 +1,23 @@ +#import +#import + +@class CAMetalLayer; + +@interface LibNativeBridge : NSObject + +@property (nonatomic, assign, getter=isInitialized) BOOL initialized; +@property (nonatomic, strong) CAMetalLayer *metalLayer; + +- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer; + +- (void)setTouchMoveWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; +- (void)setTouchUpWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; +- (void)setTouchDownWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; +- (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height; + +- (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height; +- (void)shutdown; +- (void)render; + +@end + diff --git a/Apps/Playground/visionOS/LibNativeBridge.hpp b/Apps/Playground/visionOS/LibNativeBridge.hpp deleted file mode 100644 index c1d544175..000000000 --- a/Apps/Playground/visionOS/LibNativeBridge.hpp +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef BgfxAdapter_hpp -#define BgfxAdapter_hpp - -#include -#include - -class LibNativeBridge { -private: - bool m_initialized = false; - cp_layer_renderer_t m_layerRenderer = NULL; - -public: - LibNativeBridge(cp_layer_renderer_t layerRenderer) : m_layerRenderer(layerRenderer) { - } - - ~LibNativeBridge() { - shutdown(); - } - - bool initialize(void); - void shutdown(void); - void render(void); -}; - -#endif /* BgfxAdapter_hpp */ diff --git a/Apps/Playground/visionOS/LibNativeBridge.mm b/Apps/Playground/visionOS/LibNativeBridge.mm new file mode 100644 index 000000000..86f57dfb5 --- /dev/null +++ b/Apps/Playground/visionOS/LibNativeBridge.mm @@ -0,0 +1,145 @@ +#import "LibNativeBridge.h" +#import +#import +#import +#import +#import +#import +#import +#import +#import +#import + +@implementation LibNativeBridge { + std::optional _device; + std::optional _update; + std::optional _runtime; + std::optional _nativeCanvas; + Babylon::Plugins::NativeInput* _nativeInput; + BOOL _isXrActive; +} + +- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer { + self = [super init]; + if (self) { + _metalLayer = metalLayer; + _initialized = NO; + _nativeInput = nullptr; + _isXrActive = NO; + } + return self; +} + +- (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height { + if (self.initialized) { + return YES; + } + + Babylon::Graphics::Configuration graphicsConfig{}; + graphicsConfig.Window = self.metalLayer; + graphicsConfig.Width = static_cast(width); + graphicsConfig.Height = static_cast(height); + + _device.emplace(graphicsConfig); + _update.emplace(_device->GetUpdate("update")); + + _device->StartRenderingCurrentFrame(); + _update->Start(); + + _runtime.emplace(); + + _runtime->Dispatch([self](Napi::Env env) { + self->_device->AddToJavaScript(env); + + Babylon::Polyfills::Console::Initialize(env, [](const char* message, auto) { + NSLog(@"%s", message); + }); + + self->_nativeCanvas.emplace(Babylon::Polyfills::Canvas::Initialize(env)); + + Babylon::Polyfills::Window::Initialize(env); + + Babylon::Polyfills::XMLHttpRequest::Initialize(env); + + Babylon::Plugins::NativeEngine::Initialize(env); + + Babylon::Plugins::NativeOptimizations::Initialize(env); + + self->_nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); + }); + + Babylon::ScriptLoader loader{ *_runtime }; + loader.LoadScript("app:///Scripts/ammo.js"); + loader.LoadScript("app:///Scripts/recast.js"); + loader.LoadScript("app:///Scripts/babylon.max.js"); + loader.LoadScript("app:///Scripts/babylonjs.loaders.js"); + loader.LoadScript("app:///Scripts/babylonjs.materials.js"); + loader.LoadScript("app:///Scripts/babylon.gui.js"); + loader.LoadScript("app:///Scripts/experience.js"); + self.initialized = YES; + + return YES; +} + +- (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height { + if (_device) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + + _device->UpdateSize(static_cast(width), static_cast(height)); + + _device->StartRenderingCurrentFrame(); + _update->Start(); + } +} + +- (void)setTouchUpWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { + if (_nativeInput != nullptr) { + _nativeInput->TouchUp(static_cast(pointerId), static_cast(x), static_cast(y)); + } +} + +- (void)setTouchMoveWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { + if (_nativeInput != nullptr) { + _nativeInput->TouchMove(static_cast(pointerId), static_cast(x), static_cast(y)); + } +} + +- (void)setTouchDownWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { + if (_nativeInput != nullptr) { + _nativeInput->TouchDown(static_cast(pointerId), static_cast(x), static_cast(y)); + } +} + +- (void)render { + if (_device && self.initialized) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + _device->StartRenderingCurrentFrame(); + _update->Start(); + } +} + +- (void)shutdown { + if (!self.initialized) { + return; + } + + if (_device) { + _update->Finish(); + _device->FinishRenderingCurrentFrame(); + } + + _nativeInput = nullptr; + _nativeCanvas.reset(); + _runtime.reset(); + _update.reset(); + _device.reset(); + self.initialized = NO; +} + +- (void)dealloc { + [self shutdown]; +} + +@end diff --git a/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h index 2592b6201..f64c68e75 100644 --- a/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h +++ b/Core/Graphics/Include/Platform/visionOS/Babylon/Graphics/Platform.h @@ -1,9 +1,8 @@ #pragma once -#import - +#import namespace Babylon::Graphics { - using WindowT = cp_layer_renderer_t; + using WindowT = CAMetalLayer*; } diff --git a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h index cc0de0ef9..9a42719c1 100644 --- a/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h +++ b/Core/Graphics/Include/Shared/Babylon/Graphics/Device.h @@ -4,10 +4,6 @@ #include #include -#if TARGET_OS_VISION -#include -#endif - #include #include @@ -32,10 +28,6 @@ namespace Babylon::Graphics // When enabled, back buffer will be premultiplied with alpha value. bool AlphaPremultiplied{}; - -#if TARGET_OS_VISION - ar_world_tracking_provider_t WorldTracking; -#endif }; class Device; diff --git a/Core/Graphics/Source/DeviceImpl.cpp b/Core/Graphics/Source/DeviceImpl.cpp index c9f6d6e3f..1a21f3903 100644 --- a/Core/Graphics/Source/DeviceImpl.cpp +++ b/Core/Graphics/Source/DeviceImpl.cpp @@ -44,7 +44,6 @@ namespace Babylon::Graphics init.callback = &m_bgfxCallback; init.platformData.context = config.Device; - UpdateWindow(config.Window); UpdateSize(config.Width, config.Height); UpdateMSAA(config.MSAASamples); diff --git a/Core/Graphics/Source/DeviceImpl_visionOS.mm b/Core/Graphics/Source/DeviceImpl_visionOS.mm index 2f2fdae5f..0b7ac2837 100644 --- a/Core/Graphics/Source/DeviceImpl_visionOS.mm +++ b/Core/Graphics/Source/DeviceImpl_visionOS.mm @@ -14,7 +14,8 @@ float DeviceImpl::GetDevicePixelRatio(WindowT window) { - BX_UNUSED(window); - return 2.0; + BX_UNUSED(window); + CGFloat displayScale = [UITraitCollection currentTraitCollection].displayScale; + return displayScale; } } diff --git a/Dependencies/CMakeLists.txt b/Dependencies/CMakeLists.txt index 27a8ebed2..20ea6187f 100644 --- a/Dependencies/CMakeLists.txt +++ b/Dependencies/CMakeLists.txt @@ -186,8 +186,8 @@ disable_warnings(MachineIndependent) # -------------------------------------------------- # xr # -------------------------------------------------- -# Currently supported on Windows via OpenXR, Android via ARCore, iOS and visionOS via ARKit. -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) +# Currently supported on Windows via OpenXR, Android via ARCore, and iOS via ARKit. +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) add_subdirectory(xr) set_property(TARGET xr PROPERTY FOLDER Dependencies/xr) warnings_as_errors(xr) diff --git a/Dependencies/xr/CMakeLists.txt b/Dependencies/xr/CMakeLists.txt index 66d1fafae..593b5043d 100644 --- a/Dependencies/xr/CMakeLists.txt +++ b/Dependencies/xr/CMakeLists.txt @@ -10,7 +10,7 @@ FetchContent_Declare(CMakeExtensions GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) FetchContent_Declare(ios-cmake GIT_REPOSITORY https://github.com/leetal/ios-cmake.git - GIT_TAG a52c591bc9056f3ae20a461d16fdd73ab4325be7) + GIT_TAG 4.4.1) # -------------------------------------------------- FetchContent_MakeAvailable(CMakeExtensions) @@ -22,15 +22,6 @@ if(IOS) set(DEPLOYMENT_TARGET "13" CACHE STRING "") endif() -if(VISIONOS) - FetchContent_MakeAvailable_With_Message(ios-cmake) - set(CMAKE_TOOLCHAIN_FILE "${ios-cmake_SOURCE_DIR}/ios.toolchain.cmake" CACHE PATH "") - set(PLATFORM "VISIONOSCOMBINED" CACHE STRING "") - set(DEPLOYMENT_TARGET "1.0" CACHE STRING "") - set(ENABLE_ARC OFF CACHE STRING "Enables or disables ARC support.") -endif() - - project(xr) # Avoid picking up system installed jsoncpp in favor of source distributed with openxr_loader project @@ -56,10 +47,6 @@ elseif (IOS) set(SOURCES ${SOURCES} "Source/ARKit/Include/IXrContextARKit.h" "Source/ARKit/XR.mm") -elseif (VISIONOS) - set(SOURCES ${SOURCES} - "Source/ARKit_visionOS/Include/IXrContextARKit.h" - "Source/ARKit_visionOS/XR.mm") else() set(SOURCES ${SOURCES} "Source/OpenXR/XR.cpp") @@ -104,7 +91,7 @@ if (ANDROID) set_target_properties(glm PROPERTIES INTERFACE_INCLUDE_DIRECTORIES ${arcore-android-sdk_SOURCE_DIR}/libraries/glm) target_link_libraries(xr PRIVATE glm arcore AndroidExtensions) -elseif (IOS OR VISIONOS) +elseif (IOS) target_link_libraries(xr PRIVATE "-framework ARKit") else() if(WIN32) diff --git a/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h b/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h deleted file mode 100644 index a3d2ffecd..000000000 --- a/Dependencies/xr/Source/ARKit_visionOS/Include/IXrContextARKit.h +++ /dev/null @@ -1,10 +0,0 @@ - -#pragma once - -#include - -typedef struct IXrContextARKit -{ - virtual bool IsInitialized() const = 0; - virtual ar_session_t XrSession() const = 0; -} IXrContextARKit; diff --git a/Dependencies/xr/Source/ARKit_visionOS/XR.mm b/Dependencies/xr/Source/ARKit_visionOS/XR.mm deleted file mode 100644 index b442beb45..000000000 --- a/Dependencies/xr/Source/ARKit_visionOS/XR.mm +++ /dev/null @@ -1,15 +0,0 @@ -#import -#import - -#import -#import -#import - -#import "Include/IXrContextARKit.h" - - -// TODO: Implement the visionOS ARKit api -namespace xr { -struct System::Session::Impl { -}; -} diff --git a/Plugins/CMakeLists.txt b/Plugins/CMakeLists.txt index 0f216f16c..89d8982b2 100644 --- a/Plugins/CMakeLists.txt +++ b/Plugins/CMakeLists.txt @@ -30,6 +30,6 @@ if(BABYLON_NATIVE_PLUGIN_TESTUTILS) add_subdirectory(TestUtils) endif() -if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS OR VISIONOS)) +if(BABYLON_NATIVE_PLUGIN_NATIVEXR AND (WIN32 OR ANDROID OR IOS)) add_subdirectory(NativeXr) endif() From ec56d3930902b990650accbafa3b80acf199927f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Tue, 27 Aug 2024 13:46:01 +0200 Subject: [PATCH 4/6] refactor: remove Renderer class from Swift --- Apps/Playground/visionOS/App.swift | 59 ++++-------------- Apps/Playground/visionOS/LibNativeBridge.h | 11 ++-- Apps/Playground/visionOS/LibNativeBridge.mm | 67 +++++++++++---------- 3 files changed, 53 insertions(+), 84 deletions(-) diff --git a/Apps/Playground/visionOS/App.swift b/Apps/Playground/visionOS/App.swift index ed0f5c226..53607edf1 100644 --- a/Apps/Playground/visionOS/App.swift +++ b/Apps/Playground/visionOS/App.swift @@ -1,46 +1,6 @@ import SwiftUI -class Renderer { - static var shared = Renderer() - - var displayLink: CADisplayLink? = nil - var libNativeBridge: LibNativeBridge? = nil - - var metalView: UIView? { - didSet { - libNativeBridge = LibNativeBridge(metalLayer: metalView?.layer as? CAMetalLayer) - let scale = UITraitCollection.current.displayScale - libNativeBridge?.initialize(withWidth: Int((metalView?.bounds.width ?? 0) * scale), height: Int((metalView?.bounds.height ?? 0) * scale)) - self.displayLink = CADisplayLink(target: self, selector: #selector(self.renderMetalLoop)) - self.displayLink?.add(to: .main, forMode: .common) - } - } - - init() {} - - @objc func renderMetalLoop() { - libNativeBridge?.render() - } - - func drawableWillChangeSize(width: Int, height: Int) { - libNativeBridge?.drawableWillChangeSize(withWidth: Int(width), height: Int(height)) - } - - func setTouchMove(pointerId: Int32, x: Int32, y: Int32) { - libNativeBridge?.setTouchMoveWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) - } - - func setTouchDown(pointerId: Int32, x: Int32, y: Int32) { - libNativeBridge?.setTouchDownWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) - } - - func setTouchUp(pointerId: Int32, x: Int32, y: Int32) { - libNativeBridge?.setTouchUpWithPointerId(Int(pointerId), x: Int(x), y: Int(y)) - } -} - class MetalView: UIView { - override init(frame: CGRect) { super.init(frame: frame) self.backgroundColor = .clear @@ -51,22 +11,27 @@ class MetalView: UIView { } func setupMetalLayer() { - if Renderer.shared.metalView != nil { + guard let bridge = LibNativeBridge.sharedInstance() else { return } + + if bridge.metalLayer != nil { return } self.addGestureRecognizer( UIBabylonGestureRecognizer( target: self, - onTouchDown: Renderer.shared.setTouchDown, - onTouchMove: Renderer.shared.setTouchMove, - onTouchUp: Renderer.shared.setTouchUp + onTouchDown: bridge.setTouchDown, + onTouchMove: bridge.setTouchMove, + onTouchUp: bridge.setTouchUp ) ) metalLayer.pixelFormat = .bgra8Unorm metalLayer.framebufferOnly = true - // Assign metalView to renderer - Renderer.shared.metalView = self + + bridge.metalLayer = self.metalLayer + + let scale = UITraitCollection.current.displayScale + bridge.initialize(withWidth: Int(self.bounds.width * scale), height: Int(self.bounds.height * scale)) } var metalLayer: CAMetalLayer { @@ -85,7 +50,7 @@ class MetalView: UIView { private func updateDrawableSize() { let scale = UITraitCollection.current.displayScale - Renderer.shared.drawableWillChangeSize(width: Int(bounds.width * scale), height: Int(bounds.height * scale)) + LibNativeBridge.sharedInstance().drawableWillChangeSize(withWidth: Int(bounds.width * scale), height: Int(bounds.height * scale)) metalLayer.drawableSize = CGSize(width: bounds.width * scale, height: bounds.height * scale) } } diff --git a/Apps/Playground/visionOS/LibNativeBridge.h b/Apps/Playground/visionOS/LibNativeBridge.h index 5f89a2588..0489a7068 100644 --- a/Apps/Playground/visionOS/LibNativeBridge.h +++ b/Apps/Playground/visionOS/LibNativeBridge.h @@ -8,14 +8,15 @@ @property (nonatomic, assign, getter=isInitialized) BOOL initialized; @property (nonatomic, strong) CAMetalLayer *metalLayer; -- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer; ++ (instancetype)sharedInstance; + +- (void)setTouchDown:(int)pointerId x:(int)inX y:(int)inY; +- (void)setTouchMove:(int)pointerId x:(int)inX y:(int)inY; +- (void)setTouchUp:(int)pointerId x:(int)inX y:(int)inY; -- (void)setTouchMoveWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; -- (void)setTouchUpWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; -- (void)setTouchDownWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y; - (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height; -- (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height; +- (bool)initializeWithWidth:(NSInteger)width height:(NSInteger)height; - (void)shutdown; - (void)render; diff --git a/Apps/Playground/visionOS/LibNativeBridge.mm b/Apps/Playground/visionOS/LibNativeBridge.mm index 86f57dfb5..bd3043881 100644 --- a/Apps/Playground/visionOS/LibNativeBridge.mm +++ b/Apps/Playground/visionOS/LibNativeBridge.mm @@ -11,29 +11,31 @@ #import @implementation LibNativeBridge { - std::optional _device; - std::optional _update; - std::optional _runtime; - std::optional _nativeCanvas; - Babylon::Plugins::NativeInput* _nativeInput; - BOOL _isXrActive; + std::optional _device; + std::optional _update; + std::optional _runtime; + std::optional _nativeCanvas; + Babylon::Plugins::NativeInput* _nativeInput; + bool _isXrActive; + CADisplayLink *_displayLink; } -- (instancetype)initWithMetalLayer:(CAMetalLayer *)metalLayer { - self = [super init]; - if (self) { - _metalLayer = metalLayer; - _initialized = NO; - _nativeInput = nullptr; - _isXrActive = NO; - } - return self; ++ (instancetype)sharedInstance { + static LibNativeBridge *sharedInstance = nil; + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sharedInstance = [[self alloc] init]; + }); + return sharedInstance; } -- (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height { +- (bool)initializeWithWidth:(NSInteger)width height:(NSInteger)height { if (self.initialized) { return YES; } + + _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(render)]; + [_displayLink addToRunLoop:NSRunLoop.mainRunLoop forMode:NSDefaultRunLoopMode]; Babylon::Graphics::Configuration graphicsConfig{}; graphicsConfig.Window = self.metalLayer; @@ -64,8 +66,8 @@ - (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height { Babylon::Plugins::NativeEngine::Initialize(env); Babylon::Plugins::NativeOptimizations::Initialize(env); - - self->_nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); + + _nativeInput = &Babylon::Plugins::NativeInput::CreateForJavaScript(env); }); Babylon::ScriptLoader loader{ *_runtime }; @@ -78,7 +80,7 @@ - (BOOL)initializeWithWidth:(NSInteger)width height:(NSInteger)height { loader.LoadScript("app:///Scripts/experience.js"); self.initialized = YES; - return YES; + return true; } - (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)height { @@ -93,22 +95,22 @@ - (void)drawableWillChangeSizeWithWidth:(NSInteger)width height:(NSInteger)heigh } } -- (void)setTouchUpWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { - if (_nativeInput != nullptr) { - _nativeInput->TouchUp(static_cast(pointerId), static_cast(x), static_cast(y)); - } +- (void)setTouchDown:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchDown(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } } -- (void)setTouchMoveWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { - if (_nativeInput != nullptr) { - _nativeInput->TouchMove(static_cast(pointerId), static_cast(x), static_cast(y)); - } +- (void)setTouchMove:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchMove(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } } -- (void)setTouchDownWithPointerId:(NSInteger)pointerId x:(NSInteger)x y:(NSInteger)y { - if (_nativeInput != nullptr) { - _nativeInput->TouchDown(static_cast(pointerId), static_cast(x), static_cast(y)); - } +- (void)setTouchUp:(int)pointerId x:(int)inX y:(int)inY { + if (_nativeInput) { + _nativeInput->TouchUp(static_cast(pointerId), static_cast(inX), static_cast(inY)); + } } - (void)render { @@ -124,7 +126,6 @@ - (void)shutdown { if (!self.initialized) { return; } - if (_device) { _update->Finish(); _device->FinishRenderingCurrentFrame(); @@ -135,6 +136,8 @@ - (void)shutdown { _runtime.reset(); _update.reset(); _device.reset(); + [_displayLink invalidate]; + _displayLink = NULL; self.initialized = NO; } From fe935ebee918174c6691ad55e58a4c5d88506ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Tue, 27 Aug 2024 13:55:05 +0200 Subject: [PATCH 5/6] fix: indentation --- Apps/Playground/CMakeLists.txt | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/Apps/Playground/CMakeLists.txt b/Apps/Playground/CMakeLists.txt index 1482f6c26..ecf564bf1 100644 --- a/Apps/Playground/CMakeLists.txt +++ b/Apps/Playground/CMakeLists.txt @@ -176,10 +176,10 @@ if(APPLE) # So we need to make sure we override it with nothing here in order to compile Swift. XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") - # Swift support - set(CMAKE_Swift_COMPILER_FORCED TRUE) - set(CMAKE_Swift_LANGUAGE_VERSION 4.0) - enable_language(Swift) + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 4.0) + enable_language(Swift) elseif(VISIONOS) set_target_properties(Playground PROPERTIES MACOSX_BUNDLE true @@ -201,10 +201,10 @@ if(APPLE) # So we need to make sure we override it with nothing here in order to compile Swift. XCODE_ATTRIBUTE_OTHER_SWIFT_FLAGS "") - # Swift support - set(CMAKE_Swift_COMPILER_FORCED TRUE) - set(CMAKE_Swift_LANGUAGE_VERSION 5.0) - enable_language(Swift) + # Swift support + set(CMAKE_Swift_COMPILER_FORCED TRUE) + set(CMAKE_Swift_LANGUAGE_VERSION 5.0) + enable_language(Swift) else() target_link_libraries(Playground PUBLIC "-framework MetalKit") From 028474ee0317c6451cb7f89cece56f62f2c14230 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oskar=20Kwas=CC=81niewski?= Date: Thu, 29 Aug 2024 11:00:30 +0200 Subject: [PATCH 6/6] fix: update bgfx --- CMakeLists.txt | 2 +- README.md | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e166cdde..6d55648e4 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -23,7 +23,7 @@ FetchContent_Declare(base-n GIT_TAG 7573e77c0b9b0e8a5fb63d96dbde212c921993b4) FetchContent_Declare(bgfx.cmake GIT_REPOSITORY https://github.com/BabylonJS/bgfx.cmake.git - GIT_TAG a1582009254156a0396d600265d5611bc67e85fa) + GIT_TAG 3f6a554a2f24ddb9303873dc64158a18b111f59b) FetchContent_Declare(CMakeExtensions GIT_REPOSITORY https://github.com/BabylonJS/CMakeExtensions.git GIT_TAG ea28b7689530bfdc4905806f27ecf7e8ed4b5419) diff --git a/README.md b/README.md index 253dc54b0..a5c183c79 100644 --- a/README.md +++ b/README.md @@ -22,6 +22,7 @@ Check out the [home page](https://aka.ms/Bnative) for a project overview. - [Building on Windows 10, Targeting HoloLens 2](BUILDING.md#building-on-windows-10-targeting-hololens-2) - [Building on macOS, Targeting macOS](BUILDING.md#building-on-macos-targeting-macos) - [Building on macOS, Targeting iOS](BUILDING.md#building-on-macos-targeting-ios) + - [Building on macOS, Targeting visionOS](BUILDING.md#building-on-macos-targeting-visionos) - [Building on Windows, Targeting Android](BUILDING.md#building-on-windows-targeting-android) - [Building on Ubuntu, Targeting Linux](BUILDING.md#building-on-ubuntu-targeting-linux) - [Selecting the Graphics API](BUILDING.md#selecting-the-graphics-api)