diff options
| author | Egor Yusov <egor.yusov@gmail.com> | 2018-02-09 06:08:14 +0000 |
|---|---|---|
| committer | Egor Yusov <egor.yusov@gmail.com> | 2018-02-09 06:08:14 +0000 |
| commit | 1a3598a88a30608f5f918397ae6ac37ef8c7ad2a (patch) | |
| tree | 2dc1af3f10b2e4a909679a00452da73c2cae0e23 /unityplugin/UnityEmulator | |
| parent | Updated Win32 app implementation (diff) | |
| download | DiligentEngine-1a3598a88a30608f5f918397ae6ac37ef8c7ad2a.tar.gz DiligentEngine-1a3598a88a30608f5f918397ae6ac37ef8c7ad2a.zip | |
Reworked UWP app implementation
Diffstat (limited to 'unityplugin/UnityEmulator')
19 files changed, 356 insertions, 1430 deletions
diff --git a/unityplugin/UnityEmulator/CMakeLists.txt b/unityplugin/UnityEmulator/CMakeLists.txt index d40b110..20f2347 100644 --- a/unityplugin/UnityEmulator/CMakeLists.txt +++ b/unityplugin/UnityEmulator/CMakeLists.txt @@ -49,48 +49,39 @@ if(GLES_SUPPORTED) list(APPEND INCLUDE src/Android/UnityGraphicsGLESAndroid_Impl.h)
endif()
-list(APPEND SOURCE src/UnityApp.cpp)
-
if(PLATFORM_WIN32)
list(APPEND SOURCE src/Windows/UnityAppWin32.cpp)
+ list(APPEND SOURCE src/UnityApp.cpp)
elseif(PLATFORM_UNIVERSAL_WINDOWS)
# Windows Runtime types cannot be included into static libraries
# https://social.msdn.microsoft.com/Forums/en-US/269db513-64ef-4817-a025-43954f614eb3/lnk4264-why-are-static-libraries-not-recommended-when-authoring-windows-runtime-types?forum=winappswithnativecode
# So as a workaround, we will include all source files into the target app project
- function(get_emulator_uwp_source UWP_SOURCE UWP_INCLUDE UWP_INCLUDE_DIR)
- get_target_property(EMULATOR_SOURCE_DIR UnityEmulator SOURCE_DIR)
+ function(get_emulator_uwp_source UWP_SOURCE_IN UWP_INCLUDE_IN UWP_INCLUDE_DIR_IN)
- set(${UWP_SOURCE}
- ${EMULATOR_SOURCE_DIR}/src/UWP/App.cpp
- ${EMULATOR_SOURCE_DIR}/src/UWP/DeviceResources.cpp
- ${EMULATOR_SOURCE_DIR}/src/UWP/UnityEmulatorAppMain.cpp
- PARENT_SCOPE
- )
-
- set(${UWP_INCLUDE}
- ${EMULATOR_SOURCE_DIR}/src/UWP/App.h
- ${EMULATOR_SOURCE_DIR}/src/UWP/DeviceResources.h
- ${EMULATOR_SOURCE_DIR}/src/UWP/DirectXHelper.h
- ${EMULATOR_SOURCE_DIR}/src/UWP/pch2.h
- ${EMULATOR_SOURCE_DIR}/src/UWP/StepTimer.h
- ${EMULATOR_SOURCE_DIR}/src/UWP/UnityEmulatorAppMain.h
- PARENT_SCOPE
- )
-
- set(${UWP_INCLUDE_DIR}
- ${EMULATOR_SOURCE_DIR}/Src/UWP
+ get_target_property(EMULATOR_SOURCE_DIR UnityEmulator SOURCE_DIR)
+ set(UWP_SOURCE
+ ${UWP_SOURCE_IN}
+ ${EMULATOR_SOURCE_DIR}/src/UWP/UnityAppUWP.cpp
+ ${EMULATOR_SOURCE_DIR}/src/UnityApp.cpp
PARENT_SCOPE
)
endfunction(get_emulator_uwp_source)
elseif(PLATFORM_ANDROID)
- list(APPEND SOURCE src/Android/AndroidMainImpl.cpp)
+ list(APPEND SOURCE
+ src/Android/AndroidMainImpl.cpp
+ src/UnityApp.cpp
+ )
elseif(PLATFORM_LINUX)
- list(APPEND SOURCE src/Linux/LinuxMain.cpp)
+ list(APPEND SOURCE
+ src/Linux/LinuxMain.cpp
+ src/UnityApp.cpp
+ )
elseif(PLATFORM_MACOS)
list(APPEND SOURCE
+ src/Linux/LinuxMain.cpp
src/MacOS/Renderer.cpp
)
list(APPEND INCLUDE
diff --git a/unityplugin/UnityEmulator/include/UnityApp.h b/unityplugin/UnityEmulator/include/UnityApp.h index 6cebd4c..cfc25e2 100644 --- a/unityplugin/UnityEmulator/include/UnityApp.h +++ b/unityplugin/UnityEmulator/include/UnityApp.h @@ -41,14 +41,17 @@ public: virtual void ProcessCommandLine(const char *CmdLine)override; virtual const char* GetAppTitle()const override { return m_AppTitle.c_str(); } - virtual void Initialize(const struct NativeAppAttributes &NativeAppAttribs)override; virtual void Render()override; + virtual void Present()override; virtual void Resize(int width, int height)override; virtual void Update(double CurrTime, double ElapsedTime)override; bool LoadPlugin(); protected: + virtual void InitGraphics(void *NativeWindowHandle, int WindowWidth, int WindowHeight); + virtual void InitScene(); + std::unique_ptr<UnitySceneBase> m_Scene; Diligent::DeviceType m_DeviceType = Diligent::DeviceType::Undefined; std::string m_AppTitle; diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h index 5907591..a62c05d 100644 --- a/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h +++ b/unityplugin/UnityEmulator/include/UnityGraphicsD3D11Emulator.h @@ -22,6 +22,7 @@ public: virtual UnityGfxRenderer GetUnityGfxRenderer()override final; virtual bool SwapChainInitialized()override final; void* GetD3D11Device(); + void* GetDXGISwapChain(); private: UnityGraphicsD3D11Emulator(); diff --git a/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h b/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h index b668e39..839db5a 100644 --- a/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h +++ b/unityplugin/UnityEmulator/include/UnityGraphicsD3D12Emulator.h @@ -25,6 +25,7 @@ public: virtual UnityGfxRenderer GetUnityGfxRenderer()override final; virtual bool SwapChainInitialized()override final; void* GetD3D12Device(); + void* GetDXGISwapChain(); private: UnityGraphicsD3D12Emulator(); diff --git a/unityplugin/UnityEmulator/src/UWP/App.cpp b/unityplugin/UnityEmulator/src/UWP/App.cpp deleted file mode 100644 index 7bd098f..0000000 --- a/unityplugin/UnityEmulator/src/UWP/App.cpp +++ /dev/null @@ -1,252 +0,0 @@ -/* Copyright 2015-2016 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#include "pch2.h" -#include "App.h" - -#include <ppltasks.h> - -using namespace UnityEmulatorApp; - -using namespace concurrency; -using namespace Windows::ApplicationModel; -using namespace Windows::ApplicationModel::Core; -using namespace Windows::ApplicationModel::Activation; -using namespace Windows::UI::Core; -using namespace Windows::UI::Input; -using namespace Windows::System; -using namespace Windows::Foundation; -using namespace Windows::Graphics::Display; - -using Microsoft::WRL::ComPtr; - - -// The main function is only used to initialize our IFrameworkView class. -[Platform::MTAThread] -int main(Platform::Array<Platform::String^>^) -{ - auto direct3DApplicationSource = ref new Direct3DApplicationSource(); - CoreApplication::Run(direct3DApplicationSource); - return 0; -} - -IFrameworkView^ Direct3DApplicationSource::CreateView() -{ - return ref new App(); -} - -App::App() : - m_windowClosed(false), - m_windowVisible(true) -{ -} - -// The first method called when the IFrameworkView is being created. -void App::Initialize(CoreApplicationView^ applicationView) -{ - // Register event handlers for app lifecycle. This example includes Activated, so that we - // can make the CoreWindow active and start rendering on the window. - applicationView->Activated += - ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated); - - CoreApplication::Suspending += - ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending); - - CoreApplication::Resuming += - ref new EventHandler<Platform::Object^>(this, &App::OnResuming); -} - -// Called when the CoreWindow object is created (or re-created). -void App::SetWindow(CoreWindow^ window) -{ - window->SizeChanged += - ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged); - - window->VisibilityChanged += - ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged); - - window->Closed += - ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed); - - DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); - - currentDisplayInformation->DpiChanged += - ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged); - - currentDisplayInformation->OrientationChanged += - ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged); - - DisplayInformation::DisplayContentsInvalidated += - ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated); -} - -// Initializes scene resources, or loads a previously saved app state. -void App::Load(Platform::String^ entryPoint) -{ - if (m_main == nullptr) - { - m_main = std::unique_ptr<UnityEmulatorAppMain>(new UnityEmulatorAppMain()); - } -} - -// This method is called after the window becomes active. -void App::Run() -{ - while (!m_windowClosed) - { - if (m_windowVisible) - { - CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); - - //auto commandQueue = GetDeviceResources()->GetCommandQueue(); - //PIXBeginEvent(commandQueue, 0, L"Update"); - { - m_main->Update(); - } - //PIXEndEvent(commandQueue); - - //PIXBeginEvent(commandQueue, 0, L"Render"); - { - GetDeviceResources()->BeginFrame(); - - m_main->Render(); - - GetDeviceResources()->EndFrame(); - GetDeviceResources()->Present(); - } - //PIXEndEvent(commandQueue); - } - else - { - CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); - } - } -} - -// Required for IFrameworkView. -// Terminate events do not cause Uninitialize to be called. It will be called if your IFrameworkView -// class is torn down while the app is in the foreground. -void App::Uninitialize() -{ -} - -// Application lifecycle event handlers. - -void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) -{ - // Run() won't start until the CoreWindow is activated. - CoreWindow::GetForCurrentThread()->Activate(); -} - -void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) -{ - // Save app state asynchronously after requesting a deferral. Holding a deferral - // indicates that the application is busy performing suspending operations. Be - // aware that a deferral may not be held indefinitely. After about five seconds, - // the app will be forced to exit. - SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); - - create_task([this, deferral]() - { - m_main->OnSuspending(); - deferral->Complete(); - }); -} - -void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) -{ - // Restore any data or state that was unloaded on suspend. By default, data - // and state are persisted when resuming from suspend. Note that this event - // does not occur if the app was previously terminated. - - m_main->OnResuming(); -} - -// Window event handlers. - -void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) -{ - GetDeviceResources()->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height)); - m_main->OnWindowSizeChanged(); -} - -void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) -{ - m_windowVisible = args->Visible; -} - -void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) -{ - m_windowClosed = true; -} - -// DisplayInformation event handlers. - -void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) -{ - // Note: The value for LogicalDpi retrieved here may not match the effective DPI of the app - // if it is being scaled for high resolution devices. Once the DPI is set on DeviceResources, - // you should always retrieve it using the GetDpi method. - // See DeviceResources.cpp for more details. - GetDeviceResources()->SetDpi(sender->LogicalDpi); - m_main->OnWindowSizeChanged(); -} - -void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) -{ - GetDeviceResources()->SetCurrentOrientation(sender->CurrentOrientation); - m_main->OnWindowSizeChanged(); -} - -void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) -{ - GetDeviceResources()->ValidateDevice(); -} - -std::shared_ptr<DX::DeviceResources> App::GetDeviceResources() -{ - if (m_deviceResources != nullptr && m_deviceResources->IsDeviceRemoved()) - { - // All references to the existing D3D device must be released before a new device - // can be created. - - m_deviceResources = nullptr; - m_main->OnDeviceRemoved(); - -#if defined(_DEBUG) - ComPtr<IDXGIDebug1> dxgiDebug; - if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) - { - dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); - } -#endif - } - - if (m_deviceResources == nullptr) - { - m_deviceResources = std::make_shared<DX::DeviceResources>(); - m_deviceResources->SetWindow(CoreWindow::GetForCurrentThread()); - m_main->CreateRenderers(m_deviceResources); - } - return m_deviceResources; -} diff --git a/unityplugin/UnityEmulator/src/UWP/App.h b/unityplugin/UnityEmulator/src/UWP/App.h deleted file mode 100644 index e762e8f..0000000 --- a/unityplugin/UnityEmulator/src/UWP/App.h +++ /dev/null @@ -1,75 +0,0 @@ -/* Copyright 2015-2016 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -#include "pch.h" -#include "DeviceResources.h" -#include "UnityEmulatorAppMain.h" - -namespace UnityEmulatorApp -{ - // Main entry point for our app. Connects the app with the Windows shell and handles application lifecycle events. - ref class App sealed : public Windows::ApplicationModel::Core::IFrameworkView - { - public: - App(); - - // IFrameworkView methods. - virtual void Initialize(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView); - virtual void SetWindow(Windows::UI::Core::CoreWindow^ window); - virtual void Load(Platform::String^ entryPoint); - virtual void Run(); - virtual void Uninitialize(); - - protected: - // Application lifecycle event handlers. - void OnActivated(Windows::ApplicationModel::Core::CoreApplicationView^ applicationView, Windows::ApplicationModel::Activation::IActivatedEventArgs^ args); - void OnSuspending(Platform::Object^ sender, Windows::ApplicationModel::SuspendingEventArgs^ args); - void OnResuming(Platform::Object^ sender, Platform::Object^ args); - - // Window event handlers. - void OnWindowSizeChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::WindowSizeChangedEventArgs^ args); - void OnVisibilityChanged(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::VisibilityChangedEventArgs^ args); - void OnWindowClosed(Windows::UI::Core::CoreWindow^ sender, Windows::UI::Core::CoreWindowEventArgs^ args); - - // DisplayInformation event handlers. - void OnDpiChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); - void OnOrientationChanged(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); - void OnDisplayContentsInvalidated(Windows::Graphics::Display::DisplayInformation^ sender, Platform::Object^ args); - - private: - std::shared_ptr<DX::DeviceResources> GetDeviceResources(); - - std::shared_ptr<DX::DeviceResources> m_deviceResources; - std::unique_ptr<UnityEmulatorAppMain> m_main; - bool m_windowClosed; - bool m_windowVisible; - }; -} - -ref class Direct3DApplicationSource sealed : Windows::ApplicationModel::Core::IFrameworkViewSource -{ -public: - virtual Windows::ApplicationModel::Core::IFrameworkView^ CreateView(); -}; diff --git a/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp b/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp deleted file mode 100644 index c38b510..0000000 --- a/unityplugin/UnityEmulator/src/UWP/DeviceResources.cpp +++ /dev/null @@ -1,459 +0,0 @@ -#include "pch2.h" -#include "DeviceResources.h" -#include "DirectXHelper.h" - -#include "IUnityInterface.h" -#include "UnityGraphicsD3D11Emulator.h" -#include "UnityGraphicsD3D12Emulator.h" -#include "DiligentGraphicsAdapterD3D11.h" -#include "DiligentGraphicsAdapterD3D12.h" -#include "ValidatedCast.h" - -#include "UnitySceneBase.h" -#include "StringTools.h" -#include "Errors.h" - -using namespace DirectX; -using namespace Microsoft::WRL; -using namespace Windows::Foundation; -using namespace Windows::Graphics::Display; -using namespace Windows::UI::Core; -using namespace Windows::UI::Xaml::Controls; -using namespace Platform; -using namespace Diligent; - -namespace DisplayMetrics -{ - // High resolution displays can require a lot of GPU and battery power to render. - // High resolution phones, for example, may suffer from poor battery life if - // games attempt to render at 60 frames per second at full fidelity. - // The decision to render at full fidelity across all platforms and form factors - // should be deliberate. - static const bool SupportHighResolutions = false; - - // The default thresholds that define a "high resolution" display. If the thresholds - // are exceeded and SupportHighResolutions is false, the dimensions will be scaled - // by 50%. - static const float DpiThreshold = 192.0f; // 200% of standard desktop display. - static const float WidthThreshold = 1920.0f; // 1080p width. - static const float HeightThreshold = 1080.0f; // 1080p height. -}; - -// Constants used to calculate screen rotations. -namespace ScreenRotation -{ - // 0-degree Z-rotation - static const XMFLOAT4X4 Rotation0( - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - - // 90-degree Z-rotation - static const XMFLOAT4X4 Rotation90( - 0.0f, 1.0f, 0.0f, 0.0f, - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - - // 180-degree Z-rotation - static const XMFLOAT4X4 Rotation180( - -1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, -1.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); - - // 270-degree Z-rotation - static const XMFLOAT4X4 Rotation270( - 0.0f, -1.0f, 0.0f, 0.0f, - 1.0f, 0.0f, 0.0f, 0.0f, - 0.0f, 0.0f, 1.0f, 0.0f, - 0.0f, 0.0f, 0.0f, 1.0f - ); -}; - -// Constructor for DeviceResources. -DX::DeviceResources::DeviceResources() : - m_d3dRenderTargetSize(), - m_outputSize(), - m_logicalSize(), - m_nativeOrientation(DisplayOrientations::None), - m_currentOrientation(DisplayOrientations::None), - m_dpi(-1.0f), - m_deviceRemoved(false) -{ - CreateDeviceResources(); -} - -// Configures the Direct3D device, and stores handles to it and the device context. -void DX::DeviceResources::CreateDeviceResources() -{ - switch (m_DeviceType) - { - case DeviceType::D3D11: - { - auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); - GraphicsD3D11Emulator.CreateD3D11DeviceAndContext(); - m_UnityGraphicsEmulator = &GraphicsD3D11Emulator; - m_DiligentGraphics.reset(new DiligentGraphicsAdapterD3D11(GraphicsD3D11Emulator)); - } - break; - - case DeviceType::D3D12: - { - auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); - GraphicsD3D12Emulator.CreateD3D12DeviceAndCommandQueue(); - m_UnityGraphicsEmulator = &GraphicsD3D12Emulator; - m_DiligentGraphics.reset(new DiligentGraphicsAdapterD3D12(GraphicsD3D12Emulator)); - } - break; - - default: - LOG_ERROR_AND_THROW("Unsupported device type"); - } -} - -DX::DeviceResources::~DeviceResources() -{ - m_DiligentGraphics.reset(); - m_UnityGraphicsEmulator->Release(); -} - -// These resources need to be recreated every time the window size is changed. -void DX::DeviceResources::CreateWindowSizeDependentResources() -{ - UpdateRenderTargetSize(); - - // The width and height of the swap chain must be based on the window's - // natively-oriented width and height. If the window is not in the native - // orientation, the dimensions must be reversed. - DXGI_MODE_ROTATION displayRotation = ComputeDisplayRotation(); - - bool swapDimensions = displayRotation == DXGI_MODE_ROTATION_ROTATE90 || displayRotation == DXGI_MODE_ROTATION_ROTATE270; - auto fWidth = swapDimensions ? m_outputSize.Height : m_outputSize.Width; - auto fHeight = swapDimensions ? m_outputSize.Width : m_outputSize.Height; - - UINT backBufferWidth = lround(fWidth); - UINT backBufferHeight = lround(fHeight); - - if (m_UnityGraphicsEmulator->SwapChainInitialized()) - { - m_DiligentGraphics->PreSwapChainResize(); - // If the swap chain already exists, resize it. - m_UnityGraphicsEmulator->ResizeSwapChain(backBufferWidth, backBufferHeight); - - m_DiligentGraphics->PostSwapChainResize(); - -#if 0 - if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) - { - // If the device was removed for any reason, a new device and swap chain will need to be created. - m_deviceRemoved = true; - - // Do not continue execution of this method. DeviceResources will be destroyed and re-created. - return; - } - else - { - DX::ThrowIfFailed(hr); - } -#endif - } - else - { - auto NativeWndHandle = reinterpret_cast<IUnknown*>(m_window.Get()); - switch (m_DeviceType) - { - case DeviceType::D3D11: - { - auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); - GraphicsD3D11Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); - ValidatedCast<DiligentGraphicsAdapterD3D11>(m_DiligentGraphics.get())->InitProxySwapChain(); - } - break; - - case DeviceType::D3D12: - { - auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); - GraphicsD3D12Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); - ValidatedCast<DiligentGraphicsAdapterD3D12>(m_DiligentGraphics.get())->InitProxySwapChain(); - } - break; - - default: - UNEXPECTED("Unsupported device type"); - } - } - - // Set the proper orientation for the swap chain, and generate - // 3D matrix transformations for rendering to the rotated swap chain. - // The 3D matrix is specified explicitly to avoid rounding errors. - - switch (displayRotation) - { - case DXGI_MODE_ROTATION_IDENTITY: - m_orientationTransform3D = ScreenRotation::Rotation0; - break; - - case DXGI_MODE_ROTATION_ROTATE90: - m_orientationTransform3D = ScreenRotation::Rotation270; - break; - - case DXGI_MODE_ROTATION_ROTATE180: - m_orientationTransform3D = ScreenRotation::Rotation180; - break; - - case DXGI_MODE_ROTATION_ROTATE270: - m_orientationTransform3D = ScreenRotation::Rotation90; - break; - - default: - throw ref new FailureException(); - } -#if 0 - DX::ThrowIfFailed( - m_swapChain->SetRotation(displayRotation) - ); -#endif - - -} - -// Determine the dimensions of the render target and whether it will be scaled down. -void DX::DeviceResources::UpdateRenderTargetSize() -{ - m_effectiveDpi = m_dpi; - - // To improve battery life on high resolution devices, render to a smaller render target - // and allow the GPU to scale the output when it is presented. - if (!DisplayMetrics::SupportHighResolutions && m_dpi > DisplayMetrics::DpiThreshold) - { - float width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_dpi); - float height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_dpi); - - // When the device is in portrait orientation, height > width. Compare the - // larger dimension against the width threshold and the smaller dimension - // against the height threshold. - if (max(width, height) > DisplayMetrics::WidthThreshold && min(width, height) > DisplayMetrics::HeightThreshold) - { - // To scale the app we change the effective DPI. Logical size does not change. - m_effectiveDpi /= 2.0f; - } - } - - // Calculate the necessary render target size in pixels. - m_outputSize.Width = DX::ConvertDipsToPixels(m_logicalSize.Width, m_effectiveDpi); - m_outputSize.Height = DX::ConvertDipsToPixels(m_logicalSize.Height, m_effectiveDpi); - - // Prevent zero size DirectX content from being created. - m_outputSize.Width = max(m_outputSize.Width, 1); - m_outputSize.Height = max(m_outputSize.Height, 1); -} - -// This method is called when the CoreWindow is created (or re-created). -void DX::DeviceResources::SetWindow(CoreWindow^ window) -{ - DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); - - m_window = window; - m_logicalSize = Windows::Foundation::Size(window->Bounds.Width, window->Bounds.Height); - m_nativeOrientation = currentDisplayInformation->NativeOrientation; - m_currentOrientation = currentDisplayInformation->CurrentOrientation; - m_dpi = currentDisplayInformation->LogicalDpi; - - CreateWindowSizeDependentResources(); -} - -// This method is called in the event handler for the SizeChanged event. -void DX::DeviceResources::SetLogicalSize(Windows::Foundation::Size logicalSize) -{ - if (m_logicalSize != logicalSize) - { - m_logicalSize = logicalSize; - CreateWindowSizeDependentResources(); - } -} - -// This method is called in the event handler for the DpiChanged event. -void DX::DeviceResources::SetDpi(float dpi) -{ - if (dpi != m_dpi) - { - m_dpi = dpi; - - // When the display DPI changes, the logical size of the window (measured in Dips) also changes and needs to be updated. - m_logicalSize = Windows::Foundation::Size(m_window->Bounds.Width, m_window->Bounds.Height); - - CreateWindowSizeDependentResources(); - } -} - -// This method is called in the event handler for the OrientationChanged event. -void DX::DeviceResources::SetCurrentOrientation(DisplayOrientations currentOrientation) -{ - if (m_currentOrientation != currentOrientation) - { - m_currentOrientation = currentOrientation; - CreateWindowSizeDependentResources(); - } -} - -// This method is called in the event handler for the DisplayContentsInvalidated event. -void DX::DeviceResources::ValidateDevice() -{ - // The D3D Device is no longer valid if the default adapter changed since the device - // was created or if the device has been removed. - - ComPtr<IDXGIDevice3> dxgiDevice; - ComPtr<ID3D11Device> d3d11Device; - ComPtr<ID3D12Device> d3d12Device; - - if (m_DeviceType == DeviceType::D3D11) - { - auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); - d3d11Device = reinterpret_cast<ID3D11Device*>(GraphicsD3D11Emulator.GetGraphicsImpl()); - DX::ThrowIfFailed(d3d11Device.As(&dxgiDevice)); - } - else if (m_DeviceType == DeviceType::D3D12) - { - auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); - d3d12Device = reinterpret_cast<ID3D12Device*>(GraphicsD3D12Emulator.GetGraphicsImpl()); - DX::ThrowIfFailed(d3d12Device.As(&dxgiDevice)); - } - - ComPtr<IDXGIAdapter> deviceAdapter; - DX::ThrowIfFailed(dxgiDevice->GetAdapter(&deviceAdapter)); - - ComPtr<IDXGIFactory2> deviceFactory; - DX::ThrowIfFailed(deviceAdapter->GetParent(IID_PPV_ARGS(&deviceFactory))); - - // First, get the LUID for the default adapter from when the device was created. - - DXGI_ADAPTER_DESC previousDesc; - { - ComPtr<IDXGIAdapter1> previousDefaultAdapter; - DX::ThrowIfFailed(deviceFactory->EnumAdapters1(0, &previousDefaultAdapter)); - - DX::ThrowIfFailed(previousDefaultAdapter->GetDesc(&previousDesc)); - } - - // Next, get the information for the current default adapter. - - DXGI_ADAPTER_DESC currentDesc; - { - ComPtr<IDXGIFactory4> currentDxgiFactory; - DX::ThrowIfFailed(CreateDXGIFactory1(IID_PPV_ARGS(¤tDxgiFactory))); - - ComPtr<IDXGIAdapter1> currentDefaultAdapter; - DX::ThrowIfFailed(currentDxgiFactory->EnumAdapters1(0, ¤tDefaultAdapter)); - - DX::ThrowIfFailed(currentDefaultAdapter->GetDesc(¤tDesc)); - } - - // If the adapter LUIDs don't match, or if the device reports that it has been removed, - // a new D3D device must be created. - - if (previousDesc.AdapterLuid.LowPart != currentDesc.AdapterLuid.LowPart || - previousDesc.AdapterLuid.HighPart != currentDesc.AdapterLuid.HighPart || - d3d11Device && FAILED(d3d11Device->GetDeviceRemovedReason()) || - d3d12Device && FAILED(d3d12Device->GetDeviceRemovedReason())) - { - m_deviceRemoved = true; - } -} - -void DX::DeviceResources::SetResourceStateTransitionHandler(IResourceStateTransitionHandler *pHandler) -{ - if (GetDeviceType() == DeviceType::D3D12) - { - UnityGraphicsD3D12Emulator::GetInstance().SetTransitionHandler(pHandler); - } -} - -void DX::DeviceResources::BeginFrame() -{ - m_UnityGraphicsEmulator->BeginFrame(); - m_DiligentGraphics->BeginFrame(); -} - -void DX::DeviceResources::EndFrame() -{ - m_DiligentGraphics->EndFrame(); - m_UnityGraphicsEmulator->EndFrame(); -} - -// Present the contents of the swap chain to the screen. -void DX::DeviceResources::Present() -{ - m_UnityGraphicsEmulator->Present(); - - //// If the device was removed either by a disconnection or a driver upgrade, we - //// must recreate all device resources. - //if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) - //{ - // m_deviceRemoved = true; - //} - //else - //{ - // DX::ThrowIfFailed(hr); - //} -} - - -// This method determines the rotation between the display device's native Orientation and the -// current display orientation. -DXGI_MODE_ROTATION DX::DeviceResources::ComputeDisplayRotation() -{ - DXGI_MODE_ROTATION rotation = DXGI_MODE_ROTATION_UNSPECIFIED; - - // Note: NativeOrientation can only be Landscape or Portrait even though - // the DisplayOrientations enum has other values. - switch (m_nativeOrientation) - { - case DisplayOrientations::Landscape: - switch (m_currentOrientation) - { - case DisplayOrientations::Landscape: - rotation = DXGI_MODE_ROTATION_IDENTITY; - break; - - case DisplayOrientations::Portrait: - rotation = DXGI_MODE_ROTATION_ROTATE270; - break; - - case DisplayOrientations::LandscapeFlipped: - rotation = DXGI_MODE_ROTATION_ROTATE180; - break; - - case DisplayOrientations::PortraitFlipped: - rotation = DXGI_MODE_ROTATION_ROTATE90; - break; - } - break; - - case DisplayOrientations::Portrait: - switch (m_currentOrientation) - { - case DisplayOrientations::Landscape: - rotation = DXGI_MODE_ROTATION_ROTATE90; - break; - - case DisplayOrientations::Portrait: - rotation = DXGI_MODE_ROTATION_IDENTITY; - break; - - case DisplayOrientations::LandscapeFlipped: - rotation = DXGI_MODE_ROTATION_ROTATE270; - break; - - case DisplayOrientations::PortraitFlipped: - rotation = DXGI_MODE_ROTATION_ROTATE180; - break; - } - break; - } - return rotation; -} diff --git a/unityplugin/UnityEmulator/src/UWP/DeviceResources.h b/unityplugin/UnityEmulator/src/UWP/DeviceResources.h deleted file mode 100644 index c91b055..0000000 --- a/unityplugin/UnityEmulator/src/UWP/DeviceResources.h +++ /dev/null @@ -1,71 +0,0 @@ -#pragma once - -#include "UnityGraphicsEmulator.h" -#include "DiligentGraphicsAdapter.h" -#include "ResourceStateTransitionHandler.h" - -namespace DX -{ - // Controls all the DirectX device resources. - class DeviceResources - { - public: - DeviceResources(); - ~DeviceResources(); - void SetWindow(Windows::UI::Core::CoreWindow^ window); - void SetLogicalSize(Windows::Foundation::Size logicalSize); - void SetCurrentOrientation(Windows::Graphics::Display::DisplayOrientations currentOrientation); - void SetDpi(float dpi); - void ValidateDevice(); - void BeginFrame(); - void Present(); - void EndFrame(); - DiligentGraphicsAdapter* GetDiligentGraphicsAdapter() { return m_DiligentGraphics.get(); } - UnityGraphicsEmulator* GetUnityGraphicsEmulator() { return m_UnityGraphicsEmulator;} - - Diligent::DeviceType GetDeviceType()const {return m_DeviceType;} - - // The size of the render target, in pixels. - Windows::Foundation::Size GetOutputSize() const { return m_outputSize; } - - // The size of the render target, in dips. - Windows::Foundation::Size GetLogicalSize() const { return m_logicalSize; } - - float GetDpi() const { return m_effectiveDpi; } - bool IsDeviceRemoved() const { return m_deviceRemoved; } - void SetResourceStateTransitionHandler(IResourceStateTransitionHandler *pHandler); - // D3D Accessors. - DirectX::XMFLOAT4X4 GetOrientationTransform3D() const { return m_orientationTransform3D; } - - private: - void CreateDeviceResources(); - void CreateWindowSizeDependentResources(); - void UpdateRenderTargetSize(); - DXGI_MODE_ROTATION ComputeDisplayRotation(); - - bool m_deviceRemoved = false; - - UnityGraphicsEmulator* m_UnityGraphicsEmulator = nullptr; - - std::unique_ptr<DiligentGraphicsAdapter> m_DiligentGraphics; - - // Cached reference to the Window. - Platform::Agile<Windows::UI::Core::CoreWindow> m_window; - - // Cached device properties. - Windows::Foundation::Size m_d3dRenderTargetSize; - Windows::Foundation::Size m_outputSize; - Windows::Foundation::Size m_logicalSize; - Windows::Graphics::Display::DisplayOrientations m_nativeOrientation; - Windows::Graphics::Display::DisplayOrientations m_currentOrientation; - float m_dpi; - - // This is the DPI that will be reported back to the app. It takes into account whether the app supports high resolution screens or not. - float m_effectiveDpi; - - // Transforms used for display orientation. - DirectX::XMFLOAT4X4 m_orientationTransform3D; - - Diligent::DeviceType m_DeviceType = Diligent::DeviceType::D3D12; - }; -} diff --git a/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h b/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h deleted file mode 100644 index 958b355..0000000 --- a/unityplugin/UnityEmulator/src/UWP/DirectXHelper.h +++ /dev/null @@ -1,58 +0,0 @@ -#pragma once - -#include <ppltasks.h> // For create_task - -namespace DX -{ - inline void ThrowIfFailed(HRESULT hr) - { - if (FAILED(hr)) - { - // Set a breakpoint on this line to catch Win32 API errors. - throw Platform::Exception::CreateException(hr); - } - } - - // Function that reads from a binary file asynchronously. - inline Concurrency::task<std::vector<byte>> ReadDataAsync(const std::wstring& filename) - { - using namespace Windows::Storage; - using namespace Concurrency; - - auto folder = Windows::ApplicationModel::Package::Current->InstalledLocation; - - return create_task(folder->GetFileAsync(Platform::StringReference(filename.c_str()))).then([](StorageFile^ file) - { - return FileIO::ReadBufferAsync(file); - }).then([](Streams::IBuffer^ fileBuffer) -> std::vector<byte> - { - std::vector<byte> returnBuffer; - returnBuffer.resize(fileBuffer->Length); - Streams::DataReader::FromBuffer(fileBuffer)->ReadBytes(Platform::ArrayReference<byte>(returnBuffer.data(), fileBuffer->Length)); - return returnBuffer; - }); - } - - // Converts a length in device-independent pixels (DIPs) to a length in physical pixels. - inline float ConvertDipsToPixels(float dips, float dpi) - { - static const float dipsPerInch = 96.0f; - return floorf(dips * dpi / dipsPerInch + 0.5f); // Round to nearest integer. - } - - // Assign a name to the object to aid with debugging. -#if defined(_DEBUG) - inline void SetName(ID3D12Object* pObject, LPCWSTR name) - { - pObject->SetName(name); - } -#else - inline void SetName(ID3D12Object*, LPCWSTR) - { - } -#endif -} - -// Naming helper function for ComPtr<T>. -// Assigns the name of the variable as the name of the object. -#define NAME_D3D12_OBJECT(x) DX::SetName(x.Get(), L#x) diff --git a/unityplugin/UnityEmulator/src/UWP/StepTimer.h b/unityplugin/UnityEmulator/src/UWP/StepTimer.h deleted file mode 100644 index 286710c..0000000 --- a/unityplugin/UnityEmulator/src/UWP/StepTimer.h +++ /dev/null @@ -1,183 +0,0 @@ -#pragma once - -#include <wrl.h> - -namespace DX -{ - // Helper class for animation and simulation timing. - class StepTimer - { - public: - StepTimer() : - m_elapsedTicks(0), - m_totalTicks(0), - m_leftOverTicks(0), - m_frameCount(0), - m_framesPerSecond(0), - m_framesThisSecond(0), - m_qpcSecondCounter(0), - m_isFixedTimeStep(false), - m_targetElapsedTicks(TicksPerSecond / 60) - { - if (!QueryPerformanceFrequency(&m_qpcFrequency)) - { - throw ref new Platform::FailureException(); - } - - if (!QueryPerformanceCounter(&m_qpcLastTime)) - { - throw ref new Platform::FailureException(); - } - - // Initialize max delta to 1/10 of a second. - m_qpcMaxDelta = m_qpcFrequency.QuadPart / 10; - } - - // Get elapsed time since the previous Update call. - uint64 GetElapsedTicks() const { return m_elapsedTicks; } - double GetElapsedSeconds() const { return TicksToSeconds(m_elapsedTicks); } - - // Get total time since the start of the program. - uint64 GetTotalTicks() const { return m_totalTicks; } - double GetTotalSeconds() const { return TicksToSeconds(m_totalTicks); } - - // Get total number of updates since start of the program. - uint32 GetFrameCount() const { return m_frameCount; } - - // Get the current framerate. - uint32 GetFramesPerSecond() const { return m_framesPerSecond; } - - // Set whether to use fixed or variable timestep mode. - void SetFixedTimeStep(bool isFixedTimestep) { m_isFixedTimeStep = isFixedTimestep; } - - // Set how often to call Update when in fixed timestep mode. - void SetTargetElapsedTicks(uint64 targetElapsed) { m_targetElapsedTicks = targetElapsed; } - void SetTargetElapsedSeconds(double targetElapsed) { m_targetElapsedTicks = SecondsToTicks(targetElapsed); } - - // Integer format represents time using 10,000,000 ticks per second. - static const uint64 TicksPerSecond = 10000000; - - static double TicksToSeconds(uint64 ticks) { return static_cast<double>(ticks) / TicksPerSecond; } - static uint64 SecondsToTicks(double seconds) { return static_cast<uint64>(seconds * TicksPerSecond); } - - // After an intentional timing discontinuity (for instance a blocking IO operation) - // call this to avoid having the fixed timestep logic attempt a set of catch-up - // Update calls. - - void ResetElapsedTime() - { - if (!QueryPerformanceCounter(&m_qpcLastTime)) - { - throw ref new Platform::FailureException(); - } - - m_leftOverTicks = 0; - m_framesPerSecond = 0; - m_framesThisSecond = 0; - m_qpcSecondCounter = 0; - } - - // Update timer state, calling the specified Update function the appropriate number of times. - template<typename TUpdate> - void Tick(const TUpdate& update) - { - // Query the current time. - LARGE_INTEGER currentTime; - - if (!QueryPerformanceCounter(¤tTime)) - { - throw ref new Platform::FailureException(); - } - - uint64 timeDelta = currentTime.QuadPart - m_qpcLastTime.QuadPart; - - m_qpcLastTime = currentTime; - m_qpcSecondCounter += timeDelta; - - // Clamp excessively large time deltas (e.g. after paused in the debugger). - if (timeDelta > m_qpcMaxDelta) - { - timeDelta = m_qpcMaxDelta; - } - - // Convert QPC units into a canonical tick format. This cannot overflow due to the previous clamp. - timeDelta *= TicksPerSecond; - timeDelta /= m_qpcFrequency.QuadPart; - - uint32 lastFrameCount = m_frameCount; - - if (m_isFixedTimeStep) - { - // Fixed timestep update logic - - // If the app is running very close to the target elapsed time (within 1/4 of a millisecond) just clamp - // the clock to exactly match the target value. This prevents tiny and irrelevant errors - // from accumulating over time. Without this clamping, a game that requested a 60 fps - // fixed update, running with vsync enabled on a 59.94 NTSC display, would eventually - // accumulate enough tiny errors that it would drop a frame. It is better to just round - // small deviations down to zero to leave things running smoothly. - - if (abs(static_cast<int64>(timeDelta - m_targetElapsedTicks)) < TicksPerSecond / 4000) - { - timeDelta = m_targetElapsedTicks; - } - - m_leftOverTicks += timeDelta; - - while (m_leftOverTicks >= m_targetElapsedTicks) - { - m_elapsedTicks = m_targetElapsedTicks; - m_totalTicks += m_targetElapsedTicks; - m_leftOverTicks -= m_targetElapsedTicks; - m_frameCount++; - - update(); - } - } - else - { - // Variable timestep update logic. - m_elapsedTicks = timeDelta; - m_totalTicks += timeDelta; - m_leftOverTicks = 0; - m_frameCount++; - - update(); - } - - // Track the current framerate. - if (m_frameCount != lastFrameCount) - { - m_framesThisSecond++; - } - - if (m_qpcSecondCounter >= static_cast<uint64>(m_qpcFrequency.QuadPart)) - { - m_framesPerSecond = m_framesThisSecond; - m_framesThisSecond = 0; - m_qpcSecondCounter %= m_qpcFrequency.QuadPart; - } - } - - private: - // Source timing data uses QPC units. - LARGE_INTEGER m_qpcFrequency; - LARGE_INTEGER m_qpcLastTime; - uint64 m_qpcMaxDelta; - - // Derived timing data uses a canonical tick format. - uint64 m_elapsedTicks; - uint64 m_totalTicks; - uint64 m_leftOverTicks; - - // Members for tracking the framerate. - uint32 m_frameCount; - uint32 m_framesPerSecond; - uint32 m_framesThisSecond; - uint64 m_qpcSecondCounter; - - // Members for configuring fixed timestep mode. - bool m_isFixedTimeStep; - uint64 m_targetElapsedTicks; - }; -} diff --git a/unityplugin/UnityEmulator/src/UWP/UnityAppUWP.cpp b/unityplugin/UnityEmulator/src/UWP/UnityAppUWP.cpp new file mode 100644 index 0000000..b5407b1 --- /dev/null +++ b/unityplugin/UnityEmulator/src/UWP/UnityAppUWP.cpp @@ -0,0 +1,288 @@ +/* Copyright 2015-2018 Egor Yusov +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. +* +* In no event and under no legal theory, whether in tort (including negligence), +* contract, or otherwise, unless required by applicable law (such as deliberate +* and grossly negligent acts) or agreed to in writing, shall any Contributor be +* liable for any damages, including any direct, indirect, special, incidental, +* or consequential damages of any character arising as a result of this License or +* out of the use or inability to use the software (including but not limited to damages +* for loss of goodwill, work stoppage, computer failure or malfunction, or any and +* all other commercial damages or losses), even if such Contributor has been advised +* of the possibility of such damages. +*/ + +#include "UnityApp.h" +#include "IUnityInterface.h" +#include "UnityGraphicsD3D11Emulator.h" +#include "UnityGraphicsD3D12Emulator.h" +#include "DiligentGraphicsAdapterD3D11.h" +#include "DiligentGraphicsAdapterD3D12.h" +#include "ValidatedCast.h" +#include "StringTools.h" +#include "Errors.h" + +using namespace Diligent; + +class UnityAppUWP final : public UnityApp +{ +public: + UnityAppUWP() + { + m_DeviceType = DeviceType::D3D12; + } + + virtual void OnWindowSizeChanged()override final + { + InitWindowSizeDependentResources(); + + if (m_SceneInitialized) + { + auto backBufferWidth = m_DeviceResources->GetBackBufferWidth(); + auto backBufferHeight = m_DeviceResources->GetBackBufferHeight(); + m_Scene->OnWindowResize(backBufferWidth, backBufferHeight); + } + } + + virtual void Render()override + { + // Don't try to render anything before the first Update. + if (m_timer.GetFrameCount() == 0) + { + return; + } + UnityApp::Render(); + m_bFrameReady = true; + } + + virtual void Present()override + { + m_GraphicsEmulator->Present(); + + //// If the device was removed either by a disconnection or a driver upgrade, we + //// must recreate all device resources. + //if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + //{ + // m_deviceRemoved = true; + //} + //else + //{ + // DX::ThrowIfFailed(hr); + //} + } + + virtual std::shared_ptr<DX::DeviceResources> InitDeviceResources()override + { + InitGraphics(nullptr, 0, 0); + + ID3D12Device *pd3d12Device = nullptr; + ID3D11Device *pd3d11Device = nullptr; + if (m_DeviceType == DeviceType::D3D12) + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + pd3d12Device = reinterpret_cast<ID3D12Device*>(GraphicsD3D12Emulator.GetD3D12Device()); + } + else if (m_DeviceType == DeviceType::D3D11) + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + pd3d11Device = reinterpret_cast<ID3D11Device*>(GraphicsD3D11Emulator.GetD3D11Device()); + } + else + { + UNEXPECTED("Unexpected device type"); + } + m_DeviceResources = std::make_shared<DX::DeviceResources>(pd3d11Device, pd3d12Device); + + return m_DeviceResources; + } + + virtual void InitWindowSizeDependentResources()override + { + m_DeviceResources->UpdateRenderTargetSize(); + auto backBufferWidth = m_DeviceResources->GetBackBufferWidth(); + auto backBufferHeight = m_DeviceResources->GetBackBufferHeight(); + + if (m_GraphicsEmulator->SwapChainInitialized()) + { + m_DiligentGraphics->PreSwapChainResize(); + // If the swap chain already exists, resize it. + m_GraphicsEmulator->ResizeSwapChain(backBufferWidth, backBufferHeight); + + m_DiligentGraphics->PostSwapChainResize(); +#if 0 + if (hr == DXGI_ERROR_DEVICE_REMOVED || hr == DXGI_ERROR_DEVICE_RESET) + { + // If the device was removed for any reason, a new device and swap chain will need to be created. + m_deviceRemoved = true; + + // Do not continue execution of this method. DeviceResources will be destroyed and re-created. + return; + } + else + { + DX::ThrowIfFailed(hr); + } +#endif + } + else + { + auto NativeWndHandle = reinterpret_cast<IUnknown*>(m_DeviceResources->GetWindow()); + switch (m_DeviceType) + { + case DeviceType::D3D11: + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + GraphicsD3D11Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); + ValidatedCast<DiligentGraphicsAdapterD3D11>(m_DiligentGraphics.get())->InitProxySwapChain(); + } + break; + + case DeviceType::D3D12: + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + GraphicsD3D12Emulator.CreateSwapChain(NativeWndHandle, backBufferWidth, backBufferHeight); + ValidatedCast<DiligentGraphicsAdapterD3D12>(m_DiligentGraphics.get())->InitProxySwapChain(); + } + break; + + default: + UNEXPECTED("Unsupported device type"); + } + } + + if (m_DeviceType == DeviceType::D3D12) + { + auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); + m_swapChain = reinterpret_cast<IDXGISwapChain3*>(GraphicsD3D12Emulator.GetDXGISwapChain()); + } + else if (m_DeviceType == DeviceType::D3D11) + { + auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); + auto *pSwapChain1 = reinterpret_cast<IDXGISwapChain*>(GraphicsD3D11Emulator.GetDXGISwapChain()); + pSwapChain1->QueryInterface(__uuidof(m_swapChain), reinterpret_cast<void**>(static_cast<IDXGISwapChain3**>(&m_swapChain))); + } + else + UNEXPECTED("Unexpected device type"); + m_DeviceResources->SetSwapChainRotation(m_swapChain.Get()); + } + + virtual void CreateRenderers()override + { + InitScene(); + m_SceneInitialized = true; + OnWindowSizeChanged(); + } + + + // Notifies the app that it is being suspended. + virtual void OnSuspending()override final + { + // TODO: Replace this with your app's suspending logic. + + // Process lifetime management may terminate suspended apps at any time, so it is + // good practice to save any state that will allow the app to restart where it left off. + + //m_sceneRenderer->SaveState(); + + // If your application uses video memory allocations that are easy to re-create, + // consider releasing that memory to make it available to other applications. + } + + // Notifes the app that it is no longer suspended. + virtual void OnResuming()override final + { + // TODO: Replace this with your app's resuming logic. + } + + // Notifies renderers that device resources need to be released. + virtual void OnDeviceRemoved()override final + { + // TODO: Save any necessary application or renderer state and release the renderer + // and its resources which are no longer valid. + //m_sceneRenderer->SaveState(); + m_Scene.reset(); + } + +private: + Microsoft::WRL::ComPtr<IDXGISwapChain3> m_swapChain; + bool m_SceneInitialized = false; +}; + + +NativeAppBase* CreateApplication() +{ + return new UnityAppUWP; +} + + +HMODULE g_DLLHandle; +void* UnityApp::LoadPluginFunction(const char* FunctionName) +{ + auto Func = GetProcAddress(g_DLLHandle, FunctionName); + VERIFY(Func != nullptr, "Failed to import plugin function \"", FunctionName, "\"."); + return Func; +} + +bool UnityApp::LoadPlugin() +{ + std::string LibName = m_Scene->GetPluginName(); + +#if _WIN64 +# if _M_ARM >= 7 + LibName += "_arm"; +# else + LibName += "_64"; +# endif +#else +# if _M_ARM >= 7 + LibName += "_arm"; +# else + LibName += "_32"; +# endif +#endif + +#ifdef _DEBUG + LibName += "d"; +#else + LibName += "r"; +#endif + + LibName.append(".dll"); + + auto wLibPath = WidenString(LibName); + g_DLLHandle = LoadPackagedLibrary( wLibPath.c_str(), 0); + if( g_DLLHandle == NULL ) + { + LOG_ERROR_MESSAGE( "Failed to load ", LibName, " library." ); + return false; + } + + UnityPluginLoad = reinterpret_cast<TUnityPluginLoad>( GetProcAddress(g_DLLHandle, "UnityPluginLoad") ); + UnityPluginUnload = reinterpret_cast<TUnityPluginUnload>( GetProcAddress(g_DLLHandle, "UnityPluginUnload") ); + GetRenderEventFunc = reinterpret_cast<TGetRenderEventFunc>( GetProcAddress(g_DLLHandle, "GetRenderEventFunc") ); + if( UnityPluginLoad == nullptr || UnityPluginUnload == nullptr || GetRenderEventFunc == nullptr ) + { + LOG_ERROR_MESSAGE( "Failed to import plugin functions from ", LibName, " library." ); + FreeLibrary( g_DLLHandle ); + return false; + } + + return true; +} + +void UnityApp::UnloadPlugin() +{ + m_GraphicsEmulator->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); + UnityPluginUnload(); + FreeLibrary(g_DLLHandle); + g_DLLHandle = NULL; +} diff --git a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp deleted file mode 100644 index 5b272bc..0000000 --- a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.cpp +++ /dev/null @@ -1,205 +0,0 @@ -/* Copyright 2015-2016 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#include "pch2.h" -#include "UnityEmulatorAppMain.h" -#include "DirectXHelper.h" -#include "StringTools.h" -#include "Errors.h" -#include "FileSystem.h" - -using namespace UnityEmulatorApp; -using namespace Windows::Foundation; -using namespace Windows::System::Threading; -using namespace Concurrency; -using namespace Diligent; - -// The DirectX 12 Application template is documented at http://go.microsoft.com/fwlink/?LinkID=613670&clcid=0x409 - -HMODULE UnityEmulatorAppMain::m_DLLHandle; -UnityEmulatorAppMain::TUnityPluginLoad UnityEmulatorAppMain::UnityPluginLoad; -UnityEmulatorAppMain::TUnityPluginUnload UnityEmulatorAppMain::UnityPluginUnload; -UnityEmulatorAppMain::TGetRenderEventFunc UnityEmulatorAppMain::GetRenderEventFunc; -UnityRenderingEvent UnityEmulatorAppMain::RenderEventFunc; - -void* UnityEmulatorAppMain::LoadPluginFunction(const char* FunctionName) -{ - auto Func = GetProcAddress(m_DLLHandle, FunctionName); - VERIFY( Func != nullptr, "Failed to import plugin function \"", FunctionName, "\"." ); - return Func; -} - - -bool UnityEmulatorAppMain::LoadPlugin(const char* LibPath) -{ - auto wLibPath = WidenString(LibPath); - m_DLLHandle = LoadPackagedLibrary( wLibPath.c_str(), 0); - if( m_DLLHandle == NULL ) - { - LOG_ERROR_MESSAGE( "Failed to load ", LibPath, " library." ); - return false; - } - - UnityPluginLoad = reinterpret_cast<TUnityPluginLoad>( GetProcAddress(m_DLLHandle, "UnityPluginLoad") ); - UnityPluginUnload = reinterpret_cast<TUnityPluginUnload>( GetProcAddress(m_DLLHandle, "UnityPluginUnload") ); - GetRenderEventFunc = reinterpret_cast<TGetRenderEventFunc>( GetProcAddress(m_DLLHandle, "GetRenderEventFunc") ); - if( UnityPluginLoad == nullptr || UnityPluginUnload == nullptr || GetRenderEventFunc == nullptr ) - { - LOG_ERROR_MESSAGE( "Failed to import plugin functions from ", LibPath, " library." ); - FreeLibrary( m_DLLHandle ); - return false; - } - - return true; -} - - -// Loads and initializes application assets when the application is loaded. -UnityEmulatorAppMain::UnityEmulatorAppMain() : - m_scene(CreateScene()) -{ - std::string LibName(m_scene->GetPluginName()); - -#if _WIN64 -# if _M_ARM >= 7 - LibName += "_arm"; -# else - LibName += "_64"; -# endif -#else -# if _M_ARM >= 7 - LibName += "_arm"; -# else - LibName += "_32"; -# endif -#endif - -#ifdef _DEBUG - LibName += "d"; -#else - LibName += "r"; -#endif - - LibName.append(".dll"); - if (!LoadPlugin(LibName.c_str())) - throw std::runtime_error("Failed to load plugin"); - - m_scene->OnPluginLoad(LoadPluginFunction); - - // TODO: Change the timer settings if you want something other than the default variable timestep mode. - // e.g. for 60 FPS fixed timestep update logic, call: - m_timer.SetFixedTimeStep(true); - m_timer.SetTargetElapsedSeconds(1.0 / 60); -} - -void UnityEmulatorAppMain::UnloadPlugin() -{ - m_deviceResources->GetUnityGraphicsEmulator()->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); - UnityPluginUnload(); - FreeLibrary(m_DLLHandle); - m_DLLHandle = NULL; -} - - -UnityEmulatorAppMain::~UnityEmulatorAppMain() -{ - m_scene->OnPluginUnload(); - m_scene.reset(); - UnloadPlugin(); -} - -// Creates and initializes the renderers. -void UnityEmulatorAppMain::CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources) -{ - m_deviceResources = deviceResources; - m_scene->SetDiligentGraphicsAdapter(m_deviceResources->GetDiligentGraphicsAdapter()); - m_scene->OnGraphicsInitialized(); - m_deviceResources->SetResourceStateTransitionHandler(m_scene->GetStateTransitionHandler()); - UnityPluginLoad(&m_deviceResources->GetUnityGraphicsEmulator()->GeUnityInterfaces()); - RenderEventFunc = GetRenderEventFunc(); - - OnWindowSizeChanged(); -} - -// Updates the application state once per frame. -void UnityEmulatorAppMain::Update() -{ - // Update scene objects. - m_timer.Tick([&]() - { - - }); -} - -// Renders the current frame according to the current application state. -// Returns true if the frame was rendered and is ready to be displayed. -bool UnityEmulatorAppMain::Render() -{ - // Don't try to render anything before the first Update. - if (m_timer.GetFrameCount() == 0) - { - return false; - } - - float CurrTime = static_cast<float>(m_timer.GetTotalSeconds()); - float ElapsedTime = static_cast<float>(m_timer.GetElapsedSeconds()); - m_scene->Render(RenderEventFunc, CurrTime, ElapsedTime); - - return true; -} - -// Updates application state when the window's size changes (e.g. device orientation change) -void UnityEmulatorAppMain::OnWindowSizeChanged() -{ - auto Size = m_deviceResources->GetOutputSize(); - m_scene->OnWindowResize(static_cast<int>(Size.Width), static_cast<int>(Size.Height)); -} - -// Notifies the app that it is being suspended. -void UnityEmulatorAppMain::OnSuspending() -{ - // TODO: Replace this with your app's suspending logic. - - // Process lifetime management may terminate suspended apps at any time, so it is - // good practice to save any state that will allow the app to restart where it left off. - - //m_sceneRenderer->SaveState(); - - // If your application uses video memory allocations that are easy to re-create, - // consider releasing that memory to make it available to other applications. -} - -// Notifes the app that it is no longer suspended. -void UnityEmulatorAppMain::OnResuming() -{ - // TODO: Replace this with your app's resuming logic. -} - -// Notifies renderers that device resources need to be released. -void UnityEmulatorAppMain::OnDeviceRemoved() -{ - // TODO: Save any necessary application or renderer state and release the renderer - // and its resources which are no longer valid. - //m_sceneRenderer->SaveState(); - //m_pSample = nullptr; -} diff --git a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h b/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h deleted file mode 100644 index e722907..0000000 --- a/unityplugin/UnityEmulator/src/UWP/UnityEmulatorAppMain.h +++ /dev/null @@ -1,70 +0,0 @@ - -/* Copyright 2015-2016 Egor Yusov - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS. - * - * In no event and under no legal theory, whether in tort (including negligence), - * contract, or otherwise, unless required by applicable law (such as deliberate - * and grossly negligent acts) or agreed to in writing, shall any Contributor be - * liable for any damages, including any direct, indirect, special, incidental, - * or consequential damages of any character arising as a result of this License or - * out of the use or inability to use the software (including but not limited to damages - * for loss of goodwill, work stoppage, computer failure or malfunction, or any and - * all other commercial damages or losses), even if such Contributor has been advised - * of the possibility of such damages. - */ - -#pragma once - -#include "StepTimer.h" -#include "DeviceResources.h" -#include "UnitySceneBase.h" -#include "IUnityInterface.h" - -namespace UnityEmulatorApp -{ - class UnityEmulatorAppMain - { - public: - UnityEmulatorAppMain(); - ~UnityEmulatorAppMain(); - void CreateRenderers(const std::shared_ptr<DX::DeviceResources>& deviceResources); - void Update(); - bool Render(); - - void OnWindowSizeChanged(); - void OnSuspending(); - void OnResuming(); - void OnDeviceRemoved(); - - private: - using TUnityPluginLoad = void (UNITY_INTERFACE_API *)(IUnityInterfaces* unityInterfaces); - using TUnityPluginUnload = void (UNITY_INTERFACE_API *)(); - using TGetRenderEventFunc = UnityRenderingEvent(UNITY_INTERFACE_API *)(); - - static HMODULE m_DLLHandle; - static TUnityPluginLoad UnityPluginLoad; - static TUnityPluginUnload UnityPluginUnload; - static TGetRenderEventFunc GetRenderEventFunc; - static UnityRenderingEvent RenderEventFunc; - static void* LoadPluginFunction(const char* FunctionName); - - static bool LoadPlugin(const char* LibName); - void UnloadPlugin(); - - // Cached pointer to device resources. - std::shared_ptr<DX::DeviceResources> m_deviceResources; - std::unique_ptr<UnitySceneBase> m_scene; - - // Rendering loop timer. - DX::StepTimer m_timer; - }; -} diff --git a/unityplugin/UnityEmulator/src/UWP/pch2.h b/unityplugin/UnityEmulator/src/UWP/pch2.h deleted file mode 100644 index b90e80e..0000000 --- a/unityplugin/UnityEmulator/src/UWP/pch2.h +++ /dev/null @@ -1,20 +0,0 @@ -#pragma once - -#define NOMINIMAX - -#include <wrl.h> -#include <wrl/client.h> -#include <dxgi1_4.h> -#include <d3d12.h> -#include <d3d11.h> -#include <pix.h> -#include <DirectXColors.h> -#include <DirectXMath.h> -#include <memory> -#include <vector> -#include <agile.h> -#include <concrt.h> - -#if defined(_DEBUG) -#include <dxgidebug.h> -#endif diff --git a/unityplugin/UnityEmulator/src/UnityApp.cpp b/unityplugin/UnityEmulator/src/UnityApp.cpp index 75c8a58..dc9626d 100644 --- a/unityplugin/UnityEmulator/src/UnityApp.cpp +++ b/unityplugin/UnityEmulator/src/UnityApp.cpp @@ -45,11 +45,6 @@ using namespace Diligent; -NativeAppBase* CreateApplication() -{ - return new UnityApp(); -} - UnityApp::UnityApp() : m_Scene(CreateScene()) { @@ -107,7 +102,7 @@ void UnityApp::ProcessCommandLine(const char *CmdLine) } } -void UnityApp::Initialize(const struct NativeAppAttributes &NativeAppAttribs) +void UnityApp::InitGraphics(void *NativeWindowHandle, int WindowWidth, int WindowHeight) { switch (m_DeviceType) { @@ -116,11 +111,14 @@ void UnityApp::Initialize(const struct NativeAppAttributes &NativeAppAttribs) { auto &GraphicsD3D11Emulator = UnityGraphicsD3D11Emulator::GetInstance(); GraphicsD3D11Emulator.CreateD3D11DeviceAndContext(); - GraphicsD3D11Emulator.CreateSwapChain(NativeAppAttribs.NativeWindowHandle, NativeAppAttribs.WindowWidth, NativeAppAttribs.WindowHeight); m_GraphicsEmulator = &GraphicsD3D11Emulator; auto *pDiligentAdapterD3D11 = new DiligentGraphicsAdapterD3D11(GraphicsD3D11Emulator); m_DiligentGraphics.reset(pDiligentAdapterD3D11); - pDiligentAdapterD3D11->InitProxySwapChain(); + if (NativeWindowHandle != nullptr) + { + GraphicsD3D11Emulator.CreateSwapChain(NativeWindowHandle, WindowWidth, WindowHeight); + pDiligentAdapterD3D11->InitProxySwapChain(); + } } break; #endif @@ -130,11 +128,14 @@ void UnityApp::Initialize(const struct NativeAppAttributes &NativeAppAttribs) { auto &GraphicsD3D12Emulator = UnityGraphicsD3D12Emulator::GetInstance(); GraphicsD3D12Emulator.CreateD3D12DeviceAndCommandQueue(); - GraphicsD3D12Emulator.CreateSwapChain(NativeAppAttribs.NativeWindowHandle, NativeAppAttribs.WindowWidth, NativeAppAttribs.WindowHeight); m_GraphicsEmulator = &GraphicsD3D12Emulator; auto *pDiligentAdapterD3D12 = new DiligentGraphicsAdapterD3D12(GraphicsD3D12Emulator); m_DiligentGraphics.reset(pDiligentAdapterD3D12); - pDiligentAdapterD3D12->InitProxySwapChain(); + if (NativeWindowHandle != nullptr) + { + GraphicsD3D12Emulator.CreateSwapChain(NativeWindowHandle, WindowWidth, WindowHeight); + pDiligentAdapterD3D12->InitProxySwapChain(); + } } break; #endif @@ -142,8 +143,9 @@ void UnityApp::Initialize(const struct NativeAppAttributes &NativeAppAttribs) #if OPENGL_SUPPORTED case DeviceType::OpenGL: { + VERIFY_EXPR(NativeWindowHandle != nullptr); auto &GraphicsGLCoreES_Emulator = UnityGraphicsGLCoreES_Emulator::GetInstance(); - GraphicsGLCoreES_Emulator.InitGLContext(NativeAppAttribs.NativeWindowHandle, 4, 4); + GraphicsGLCoreES_Emulator.InitGLContext(NativeWindowHandle, 4, 4); m_GraphicsEmulator = &GraphicsGLCoreES_Emulator; m_DiligentGraphics.reset(new DiligentGraphicsAdapterGL(GraphicsGLCoreES_Emulator)); } @@ -153,7 +155,10 @@ void UnityApp::Initialize(const struct NativeAppAttributes &NativeAppAttribs) default: LOG_ERROR_AND_THROW("Unsupported device type"); } +} +void UnityApp::InitScene() +{ m_Scene->SetDiligentGraphicsAdapter(m_DiligentGraphics.get()); m_Scene->OnGraphicsInitialized(); if (m_DeviceType == DeviceType::D3D12) @@ -186,7 +191,10 @@ void UnityApp::Render() m_DiligentGraphics->EndFrame(); m_GraphicsEmulator->EndFrame(); +} +void UnityApp::Present() +{ m_GraphicsEmulator->Present(); } diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp index 2f5dfc6..7eeca7a 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Emulator.cpp @@ -324,6 +324,12 @@ void* UnityGraphicsD3D11Emulator::GetD3D11Device() return m_GraphicsImpl->GetD3D11Device(); } +void* UnityGraphicsD3D11Emulator::GetDXGISwapChain() +{ + return m_GraphicsImpl->GetDXGISwapChain(); +} + + static ID3D11Device* UNITY_INTERFACE_API UnityGraphicsD3D11_GetDevice() { auto *GraphicsImpl = UnityGraphicsD3D11Emulator::GetGraphicsImpl(); diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h index 183522f..0377081 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D11Impl.h @@ -22,6 +22,7 @@ public: ID3D11Device* GetD3D11Device() { return m_d3d11Device; } + IDXGISwapChain* GetDXGISwapChain() { return m_SwapChain; } ID3D11DeviceContext* GetD3D11Context() { return m_d3d11Context; } ID3D11RenderTargetView* GetRTV() { return m_BackBufferRTV; } ID3D11DepthStencilView* GetDSV() { return m_DepthBufferDSV; } diff --git a/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp index ce42b31..1d68f0a 100644 --- a/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp +++ b/unityplugin/UnityEmulator/src/UnityGraphicsD3D12Emulator.cpp @@ -331,6 +331,10 @@ void* UnityGraphicsD3D12Emulator::GetD3D12Device() return m_GraphicsImpl->GetD3D12Device(); } +void* UnityGraphicsD3D12Emulator::GetDXGISwapChain() +{ + return m_GraphicsImpl->GetDXGISwapChain(); +} CComPtr<ID3D12CommandAllocator> UnityGraphicsD3D12Impl::GetCommandAllocator() { diff --git a/unityplugin/UnityEmulator/src/Windows/UnityAppWin32.cpp b/unityplugin/UnityEmulator/src/Windows/UnityAppWin32.cpp index 2fe174c..8b56b4e 100644 --- a/unityplugin/UnityEmulator/src/Windows/UnityAppWin32.cpp +++ b/unityplugin/UnityEmulator/src/Windows/UnityAppWin32.cpp @@ -31,6 +31,21 @@ HMODULE g_DLLHandle; +class UnityAppWin32 : public UnityApp +{ +public: + virtual void OnWindowCreated(HWND hWnd, LONG WindowWidth, LONG WindowHeight)override final + { + InitGraphics(hWnd, WindowWidth, WindowHeight); + InitScene(); + } +}; + +NativeAppBase* CreateApplication() +{ + return new UnityAppWin32(); +} + void* UnityApp::LoadPluginFunction(const char* FunctionName) { auto Func = GetProcAddress(g_DLLHandle, FunctionName); @@ -79,4 +94,5 @@ void UnityApp::UnloadPlugin() m_GraphicsEmulator->InvokeDeviceEventCallback(kUnityGfxDeviceEventShutdown); UnityPluginUnload(); FreeLibrary(g_DLLHandle); + g_DLLHandle = NULL; } |
