Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)

project(BabylonNative)

set(SUPPORTED_PLATFORMS "Win32" "Android")
set(SUPPORTED_PLATFORMS "Win32" "UWP" "Android")
if (ANDROID)
set(BABYLON_NATIVE_PLATFORM "Android" CACHE STRING "Target platform for Babylon Native.")
set(BABYLON_NATIVE_PLATFORM "Android" CACHE STRING "Target platform for Babylon Native.")
else()
set(BABYLON_NATIVE_PLATFORM "Win32" CACHE STRING "Target platform for Babylon Native.")
set(BABYLON_NATIVE_PLATFORM "Win32" CACHE STRING "Target platform for Babylon Native.")
endif()

if(NOT(BABYLON_NATIVE_PLATFORM IN_LIST SUPPORTED_PLATFORMS))
message(FATAL_ERROR "Unrecognized platform: ${BABYLON_NATIVE_PLATFORM}")
endif()

if(BABYLON_NATIVE_PLATFORM STREQUAL "UWP" AND NOT(WINDOWS_STORE))
message(FATAL_ERROR "\nUWP builds must target Windows Store. Make sure to designate\n\t\"-D CMAKE_SYSTEM_NAME=WindowsStore -D CMAKE_SYSTEM_VERSION=10.0\"\nwhen configuring for UWP.")
endif()

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

if(${CMAKE_CXX_COMPILER} MATCHES "x86/cl.exe$")
if(ANDROID)
set(ARCH ${ANDROID_ABI})
elseif(${CMAKE_CXX_COMPILER} MATCHES "x86/cl.exe$")
set(ARCH "x86")
elseif(${CMAKE_CXX_COMPILER} MATCHES "x64/cl.exe$")
set(ARCH "x64")
elseif(ANDROID)
set(ARCH ${ANDROID_ABI})
elseif(${CMAKE_CXX_COMPILER} MATCHES "arm/cl.exe$")
set(ARCH "ARM")
else()
message(FATAL_ERROR "Unrecognized compiler: ${CMAKE_CXX_COMPILER}")
endif()
Expand Down
22 changes: 22 additions & 0 deletions Library/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
add_subdirectory(Dependencies/arcana.cpp EXCLUDE_FROM_ALL)
set_property(TARGET arcana PROPERTY FOLDER Dependencies/arcana)

set(NAPI_JAVASCRIPT_ENGINE "Chakra" CACHE STRING "JavaScript engine for N-API.")
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
Expand Down Expand Up @@ -42,6 +45,13 @@ set(CMAKE_USE_WINSSL ON CACHE BOOL "Set cURL to use WinSSL by default.")
add_subdirectory(Dependencies/curl EXCLUDE_FROM_ALL)
set_property(TARGET libcurl PROPERTY FOLDER Dependencies/curl)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opening an issue to track the following TODO.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

#28

# TODO: Certain parts of cURL's functionality are gated behind WINAPI checks
# that cause the functionality to become unavailable in UWP. Find a better way
# to ensure that functionality is enabled, then remove the following workaround.
if(WINDOWS_STORE)
target_compile_definitions(libcurl PRIVATE "WINAPI_PARTITION_DESKTOP=1")
endif()

set(SOURCES
"Include/Babylon/Runtime.h"
"Include/Babylon/Runtime${BABYLON_NATIVE_PLATFORM}.h"
Expand Down Expand Up @@ -104,6 +114,10 @@ target_include_directories(Library PRIVATE "Dependencies/curl/include")
target_include_directories(Library PRIVATE "Dependencies/glslang")
target_include_directories(Library PRIVATE "Dependencies/SPIRV-Cross")

if(WINDOWS_STORE)
target_include_directories(Library PRIVATE "Dependencies/arcana.cpp/Source/UWP")
endif()

target_link_libraries(Library
PRIVATE bx
PRIVATE bimg
Expand All @@ -113,6 +127,10 @@ target_link_libraries(Library
PRIVATE SPIRV
PRIVATE spirv-cross-hlsl)

if(WINDOWS_STORE)
target_link_libraries(Library PRIVATE arcana)
endif()

target_link_libraries(Library
PRIVATE "crypt32.lib"
PRIVATE "d2d1.lib"
Expand All @@ -127,6 +145,10 @@ target_link_libraries(Library
PRIVATE "ws2_32.lib"
PRIVATE "wldap32.lib")

if(WINDOWS_STORE)
target_link_libraries(Library PRIVATE "kernel32.lib")
endif()

target_include_directories(Library PUBLIC "Include")
target_link_libraries(Library PUBLIC napi)

2 changes: 1 addition & 1 deletion Library/Dependencies/arcana.cpp
2 changes: 1 addition & 1 deletion Library/Dependencies/bgfx.cmake
Submodule bgfx.cmake updated 5 files
+1 −1 bgfx
+1 −1 bimg
+1 −1 bx
+5 −0 cmake/3rdparty/nvtt.cmake
+10 −0 cmake/bx.cmake
1 change: 1 addition & 0 deletions Library/Dependencies/napi/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ endif()
add_library(napi ${SOURCES})

target_compile_definitions(napi PRIVATE NOMINMAX)
target_compile_definitions(napi PRIVATE _CRT_SECURE_NO_WARNINGS)

target_compile_definitions(napi PUBLIC NODE_ADDON_API_DISABLE_DEPRECATED)

Expand Down
15 changes: 8 additions & 7 deletions Library/Include/Babylon/RuntimeUWP.h
Original file line number Diff line number Diff line change
@@ -1,23 +1,24 @@
#pragma once

#include "Runtime.h"

#include <windows.ui.core.h>
#include <windows.ui.xaml.controls.h>

#include <memory>

namespace babylon
{
class Runtime;

class RuntimeUWP final : public Runtime
{
public:
explicit RuntimeUWP(ABI::Windows::UI::Core::ICoreWindow* window, const std::string& rootUrl = {});
explicit RuntimeUWP(ABI::Windows::UI::Xaml::Controls::ISwapChainPanel* panel, const std::string& rootUrl = {});

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Opening an issue to track the following TODO.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a line in the Feature Backlog (#6)

// TODO: Allow creation from swap chain, which is required by XAML apps.
// explicit RuntimeUWP(ABI::Windows::UI::Xaml::Controls::ISwapChainPanel* panel, const std::string& rootUrl = {});

RuntimeUWP(const Runtime&) = delete;
~RuntimeUWP() = default;
~RuntimeUWP();

private:
class Impl;
ABI::Windows::UI::Core::ICoreWindow* m_window{};
};
}
1 change: 1 addition & 0 deletions Library/Source/CommonUWP.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@ namespace babylon
std::string GetUrlFromPath(const std::filesystem::path& path)
{
// TODO: implement with Windows::Foundation::Uri
throw std::exception("Not implemented!");
}
}
187 changes: 12 additions & 175 deletions Library/Source/RuntimeUWP.cpp
Original file line number Diff line number Diff line change
@@ -1,191 +1,28 @@
#include "RuntimeUWP.h"
#include "CommonUWP.h"
#include "Babylon/Runtime.h"
#include "Babylon/RuntimeUWP.h"
#include "RuntimeImpl.h"
#include <ScriptHost/ScriptHost.h>
#include <ScriptHost/Console.h>
#include <ScriptHost/Window.h>
#include <ScriptHost/XMLHttpRequest.h>
#include <arcana/experimental/array.h>
#include <arcana/threading/cancellation.h>
#include <arcana/threading/coroutine.h>
#include <arcana/threading/dispatcher.h>
#include <arcana/threading/task.h>
#include <arcana/threading/task_conversions.h>
#include <winrt/Windows.ApplicationModel.h>
#include <winrt/Windows.ApplicationModel.Core.h>
#include <winrt/Windows.UI.Core.h>
#include <winrt/Windows.Storage.h>
#include <winrt/Windows.Graphics.Display.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <exception>
#include <dxgi1_2.h>
#include <windows.ui.xaml.media.dxinterop.h>
#include <variant>

namespace
{
arcana::task<std::string, std::exception_ptr> read_text_async(std::string filename)
{
auto folder = winrt::Windows::ApplicationModel::Package::Current().InstalledLocation();
return arcana::create_task<std::exception_ptr>(folder.GetFileAsync(winrt::to_hstring(filename)))
.then(arcana::inline_scheduler, arcana::cancellation::none(), [filename](const winrt::Windows::Storage::StorageFile& file)
{
return arcana::create_task<std::exception_ptr>(winrt::Windows::Storage::FileIO::ReadTextAsync(file));
}).then(arcana::inline_scheduler, arcana::cancellation::none(), [filename](const winrt::hstring& hstring)
{
return winrt::to_string(hstring);
});
}

// Converts a length in device-independent pixels (DIPs) to a length in physical pixels.
float dips_to_pixels(float dips, float dpi)
{
static const float dipsPerInch = 96.0f;
return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer.
}

template<typename T>
T from_abi(void* from)
{
T to{ nullptr };
winrt::copy_from_abi(to, from);
return std::move(to);
}

// TODO: fix for bgfx
//Spectre::Engine::EngineDescription GetEngineDescription(winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow>& window)
//{
// Spectre::Engine::EngineDescription engineDesc{};

// Spectre::Engine::GeneralDescription& general = engineDesc.General;
// general.ThreadingMode = Spectre::Engine::Lockable::ThreadingMode::Single;

// Spectre::Engine::DeviceDescription& device = engineDesc.Device;
// device.Platform = Spectre::Engine::DevicePlatform::DirectX11;

// Spectre::Engine::OutputDescription& output = engineDesc.Output;
// output.Mode = Spectre::Engine::RenderOutputMode::CoreWindow;
// output.NativeWindow = winrt::get_abi(reinterpret_cast<winrt::com_ptr<IAgileReference>&>(window));
// output.PerformanceLogging = Spectre::Engine::RenderOutputPerformanceLogging::Enable;

// return std::move(engineDesc);
//}

//void SPECTRESDK_CALL OnSwapChainCreatedCallback(void* dxgiSwapChain, void* pUserData)
//{
// auto panel = from_abi<winrt::Windows::UI::Xaml::Controls::SwapChainPanel>(pUserData);
// panel.Dispatcher().RunAsync(winrt::Windows::UI::Core::CoreDispatcherPriority::Normal, [=]
// {
// winrt::check_hresult(panel.as<ISwapChainPanelNative>()->SetSwapChain(static_cast<IDXGISwapChain1*>(dxgiSwapChain)));
// });
//}

//Spectre::Engine::EngineDescription GetEngineDescription(winrt::Windows::UI::Xaml::Controls::SwapChainPanel& panel)
//{
// Spectre::Engine::EngineDescription engineDesc{};

// Spectre::Engine::GeneralDescription& general = engineDesc.General;
// general.ThreadingMode = Spectre::Engine::Lockable::ThreadingMode::Single;

// Spectre::Engine::DeviceDescription& device = engineDesc.Device;
// device.Platform = Spectre::Engine::DevicePlatform::DirectX11;

// Spectre::Engine::OutputDescription& output = engineDesc.Output;
// output.Mode = Spectre::Engine::RenderOutputMode::XAML;
// output.NativeWindow = winrt::get_abi(panel);
// output.OnSwapChainCreatedCallback = OnSwapChainCreatedCallback;
// output.PerformanceLogging = Spectre::Engine::RenderOutputPerformanceLogging::Enable;

// return std::move(engineDesc);
//}
}

namespace babylon
{
class RuntimeUWP::Impl final : public RuntimeImpl
{
public:
// TODO: fix RenderPAL to take a CoreWindow directly instead of an agile ref to a CoreWindow once we switch to RenderPAL.
explicit Impl(winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow> window, const std::string& rootUrl);
explicit Impl(winrt::Windows::UI::Xaml::Controls::SwapChainPanel panel, const std::string& rootUrl);
~Impl() override = default;

virtual void RunScript(const std::string& url) override;
virtual void RunScript(const std::string& script, const std::string& url) override;

private:
std::variant<winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow>, winrt::Windows::UI::Xaml::Controls::SwapChainPanel> m_windowsUiContext;
};

RuntimeUWP::DefaultInitializationScriptsArray RuntimeUWP::DEFAULT_INITIALIZATION_SCRIPTS = arcana::make_array<std::string>
(
#ifdef _DEBUG
"Scripts\\babylon.max.js",
"Scripts\\babylon.glTF2FileLoader.js"
#else
"Scripts\\babylon.js",
"Scripts\\babylon.glTF2FileLoader.min.js"
#endif
);

RuntimeUWP::RuntimeUWP(ABI::Windows::UI::Core::ICoreWindow* window, const std::string& rootUrl)
: Runtime{ std::make_unique<RuntimeUWP::Impl>(from_abi<winrt::Windows::UI::Core::CoreWindow>(window), rootUrl) }
: Runtime { std::make_unique<RuntimeImpl>(window, rootUrl) }
, m_window{ window }
{
m_window->AddRef();
}

RuntimeUWP::RuntimeUWP(ABI::Windows::UI::Xaml::Controls::ISwapChainPanel* panel, const std::string& rootUrl)
: Runtime{ std::make_unique<RuntimeUWP::Impl>(from_abi<winrt::Windows::UI::Xaml::Controls::SwapChainPanel>(panel), rootUrl) }
RuntimeUWP::~RuntimeUWP()
{
m_window->Release();
}

RuntimeUWP::Impl::Impl(winrt::agile_ref<winrt::Windows::UI::Core::CoreWindow> window, const std::string& rootUrl)
: RuntimeImpl{ /*std::make_unique<SpectreEngine>(GetEngineDescription(window), *this)*/nullptr, rootUrl }
, m_windowsUiContext{ window }
/*RuntimeUWP::RuntimeUWP(ABI::Windows::UI::Xaml::Controls::ISwapChainPanel* panel, const std::string& rootUrl)
: Runtime{ std::make_unique<RuntimeImpl>(from_abi<winrt::Windows::UI::Xaml::Controls::SwapChainPanel>(panel), rootUrl) }
{
// Set initial render output size.
const auto windowBounds = window.get().Bounds();
const auto currentDisplayInformation = winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView();
const float dpi = currentDisplayInformation.LogicalDpi();
UpdateSize(dips_to_pixels(windowBounds.Width, dpi), dips_to_pixels(windowBounds.Height, dpi));

for (const auto& url : RuntimeUWP::DEFAULT_INITIALIZATION_SCRIPTS)
{
RunScript(url);
}
}

RuntimeUWP::Impl::Impl(winrt::Windows::UI::Xaml::Controls::SwapChainPanel panel, const std::string& rootUrl)
: RuntimeImpl{ /*std::make_unique<SpectreEngine>(GetEngineDescription(panel), *this)*/nullptr, rootUrl }
, m_windowsUiContext{ panel }
{
// Set initial render output size.
const auto currentDisplayInformation = winrt::Windows::Graphics::Display::DisplayInformation::GetForCurrentView();
const float dpi = currentDisplayInformation.LogicalDpi();
UpdateSize(dips_to_pixels(static_cast<float>(panel.ActualWidth()), dpi), dips_to_pixels(static_cast<float>(panel.ActualHeight()), dpi));

for (const auto& url : RuntimeUWP::DEFAULT_INITIALIZATION_SCRIPTS)
{
RunScript(url);
}
}

void RuntimeUWP::Impl::RunScript(const std::string& url)
{
auto lock = AcquireTaskLock();
Task = Task.then(arcana::inline_scheduler, Cancellation(), [url]
{
return read_text_async(url);
}).then(Dispatcher(), Cancellation(), [this, url](const std::string& script)
{
RunScriptWithNapi(script, url);
});
}
}*/

void RuntimeUWP::Impl::RunScript(const std::string& script, const std::string& url)
void RuntimeImpl::ThreadProcedure()
{
Execute([this, script, url](auto&)
{
RunScriptWithNapi(script, url);
});
RuntimeImpl::BaseThreadProcedure();
}
}
10 changes: 7 additions & 3 deletions Library/Source/XMLHttpRequestUWP.cpp
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
#include "XMLHttpRequest.h"

#include <Runtime/Common.h>
#include "Common.h"
#include "RuntimeImpl.h"

#include <arcana/threading/task_conversions.h>
#include <robuffer.h>
#include <winrt/Windows.Storage.Streams.h>

// Included after the WinRT headers because they enable non-WinRT interfaces. If this were included before
// the WinRT headers, we'd have to explicitly include unknwn.h, or build would fail with C2338.
#include <arcana/threading/task_conversions.h>

namespace babylon
{
arcana::task<void, std::exception_ptr> XMLHttpRequest::SendAsync()
Expand Down Expand Up @@ -59,7 +63,7 @@ namespace babylon
}).then(m_runtimeImpl.Dispatcher(), m_runtimeImpl.Cancellation(), [this, url = std::move(url)]
{
m_responseURL = url;
m_status = winrt::Windows::Web::Http::HttpStatusCode::Ok;
m_status = HTTPStatusCode::Ok;

SetReadyState(ReadyState::Done);
});
Expand Down
Loading