|
| 1 | +#include "pch.h" |
| 2 | +#include "App.h" |
| 3 | + |
| 4 | +#include <ppltasks.h> |
| 5 | + |
| 6 | +using namespace DirectX12UWPTessellation; |
| 7 | + |
| 8 | +using namespace concurrency; |
| 9 | +using namespace Windows::ApplicationModel; |
| 10 | +using namespace Windows::ApplicationModel::Core; |
| 11 | +using namespace Windows::ApplicationModel::Activation; |
| 12 | +using namespace Windows::UI::Core; |
| 13 | +using namespace Windows::UI::Input; |
| 14 | +using namespace Windows::System; |
| 15 | +using namespace Windows::Foundation; |
| 16 | +using namespace Windows::Graphics::Display; |
| 17 | + |
| 18 | +using Microsoft::WRL::ComPtr; |
| 19 | + |
| 20 | +// DirectX 12 应用程序模板记录在 http://go.microsoft.com/fwlink/?LinkID=613670&clcid=0x409 处 |
| 21 | + |
| 22 | +// 主函数仅用于初始化我们的 IFrameworkView 类。 |
| 23 | +[Platform::MTAThread] |
| 24 | +int main(Platform::Array<Platform::String^>^) |
| 25 | +{ |
| 26 | + auto direct3DApplicationSource = ref new Direct3DApplicationSource(); |
| 27 | + CoreApplication::Run(direct3DApplicationSource); |
| 28 | + return 0; |
| 29 | +} |
| 30 | + |
| 31 | +IFrameworkView^ Direct3DApplicationSource::CreateView() |
| 32 | +{ |
| 33 | + return ref new App(); |
| 34 | +} |
| 35 | + |
| 36 | +App::App() : |
| 37 | + m_windowClosed(false), |
| 38 | + m_windowVisible(true) |
| 39 | +{ |
| 40 | +} |
| 41 | + |
| 42 | +// 创建 IFrameworkView 时调用的第一个方法。 |
| 43 | +void App::Initialize(CoreApplicationView^ applicationView) |
| 44 | +{ |
| 45 | + // 注册应用生命周期的事件处理程序。此示例包括 Activated,因此我们 |
| 46 | + // 可激活 CoreWindow 并开始在窗口上渲染。 |
| 47 | + applicationView->Activated += |
| 48 | + ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &App::OnActivated); |
| 49 | + |
| 50 | + CoreApplication::Suspending += |
| 51 | + ref new EventHandler<SuspendingEventArgs^>(this, &App::OnSuspending); |
| 52 | + |
| 53 | + CoreApplication::Resuming += |
| 54 | + ref new EventHandler<Platform::Object^>(this, &App::OnResuming); |
| 55 | +} |
| 56 | + |
| 57 | +// 创建(或重新创建) CoreWindow 对象时调用。 |
| 58 | +void App::SetWindow(CoreWindow^ window) |
| 59 | +{ |
| 60 | + window->SizeChanged += |
| 61 | + ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &App::OnWindowSizeChanged); |
| 62 | + |
| 63 | + window->VisibilityChanged += |
| 64 | + ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &App::OnVisibilityChanged); |
| 65 | + |
| 66 | + window->Closed += |
| 67 | + ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &App::OnWindowClosed); |
| 68 | + |
| 69 | + DisplayInformation^ currentDisplayInformation = DisplayInformation::GetForCurrentView(); |
| 70 | + |
| 71 | + currentDisplayInformation->DpiChanged += |
| 72 | + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDpiChanged); |
| 73 | + |
| 74 | + currentDisplayInformation->OrientationChanged += |
| 75 | + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnOrientationChanged); |
| 76 | + |
| 77 | + DisplayInformation::DisplayContentsInvalidated += |
| 78 | + ref new TypedEventHandler<DisplayInformation^, Object^>(this, &App::OnDisplayContentsInvalidated); |
| 79 | +} |
| 80 | + |
| 81 | +// 初始化场景资源或加载之前保存的应用状态。 |
| 82 | +void App::Load(Platform::String^ entryPoint) |
| 83 | +{ |
| 84 | + if (m_main == nullptr) |
| 85 | + { |
| 86 | + m_main = std::unique_ptr<DirectX12UWPTessellationMain>(new DirectX12UWPTessellationMain()); |
| 87 | + } |
| 88 | +} |
| 89 | + |
| 90 | +// 将在窗口处于活动状态后调用此方法。 |
| 91 | +void App::Run() |
| 92 | +{ |
| 93 | + while (!m_windowClosed) |
| 94 | + { |
| 95 | + if (m_windowVisible) |
| 96 | + { |
| 97 | + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent); |
| 98 | + |
| 99 | + auto commandQueue = GetDeviceResources()->GetCommandQueue(); |
| 100 | + PIXBeginEvent(commandQueue, 0, L"Update"); |
| 101 | + { |
| 102 | + m_main->Update(); |
| 103 | + } |
| 104 | + PIXEndEvent(commandQueue); |
| 105 | + |
| 106 | + PIXBeginEvent(commandQueue, 0, L"Render"); |
| 107 | + { |
| 108 | + if (m_main->Render()) |
| 109 | + { |
| 110 | + GetDeviceResources()->Present(); |
| 111 | + } |
| 112 | + } |
| 113 | + PIXEndEvent(commandQueue); |
| 114 | + } |
| 115 | + else |
| 116 | + { |
| 117 | + CoreWindow::GetForCurrentThread()->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessOneAndAllPending); |
| 118 | + } |
| 119 | + } |
| 120 | +} |
| 121 | + |
| 122 | +// IFrameworkView 所必需的。 |
| 123 | +// 终止事件不会导致调用 Uninitialize。如果在应用在前台运行时销毁 IFrameworkView |
| 124 | +// 类,则将调用该方法。 |
| 125 | +void App::Uninitialize() |
| 126 | +{ |
| 127 | +} |
| 128 | + |
| 129 | +// 应用程序生命周期事件处理程序。 |
| 130 | + |
| 131 | +void App::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args) |
| 132 | +{ |
| 133 | + // Run() 在 CoreWindow 激活前将不会开始。 |
| 134 | + CoreWindow::GetForCurrentThread()->Activate(); |
| 135 | +} |
| 136 | + |
| 137 | +void App::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) |
| 138 | +{ |
| 139 | + // 在请求延期后异步保存应用状态。保留延期 |
| 140 | + // 表示应用程序正忙于执行挂起操作。 |
| 141 | + // 请注意,延期不是无限期的。在大约五秒后, |
| 142 | + // 将强制应用退出。 |
| 143 | + SuspendingDeferral^ deferral = args->SuspendingOperation->GetDeferral(); |
| 144 | + |
| 145 | + create_task([this, deferral]() |
| 146 | + { |
| 147 | + m_main->OnSuspending(); |
| 148 | + deferral->Complete(); |
| 149 | + }); |
| 150 | +} |
| 151 | + |
| 152 | +void App::OnResuming(Platform::Object^ sender, Platform::Object^ args) |
| 153 | +{ |
| 154 | + // 还原在挂起时卸载的任何数据或状态。默认情况下, |
| 155 | + // 在从挂起中恢复时,数据和状态会持续保留。请注意, |
| 156 | + // 如果之前已终止应用,则不会发生此事件。 |
| 157 | + |
| 158 | + m_main->OnResuming(); |
| 159 | +} |
| 160 | + |
| 161 | +// 窗口事件处理程序。 |
| 162 | + |
| 163 | +void App::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args) |
| 164 | +{ |
| 165 | + GetDeviceResources()->SetLogicalSize(Size(sender->Bounds.Width, sender->Bounds.Height)); |
| 166 | + m_main->OnWindowSizeChanged(); |
| 167 | +} |
| 168 | + |
| 169 | +void App::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) |
| 170 | +{ |
| 171 | + m_windowVisible = args->Visible; |
| 172 | +} |
| 173 | + |
| 174 | +void App::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args) |
| 175 | +{ |
| 176 | + m_windowClosed = true; |
| 177 | +} |
| 178 | + |
| 179 | +// DisplayInformation 事件处理程序。 |
| 180 | + |
| 181 | +void App::OnDpiChanged(DisplayInformation^ sender, Object^ args) |
| 182 | +{ |
| 183 | + // 注意: 在此处检索到的 LogicalDpi 值可能与应用的有效 DPI 不匹配 |
| 184 | + // 如果正在针对高分辨率设备对它进行缩放。在 DeviceResources 上设置 DPI 后, |
| 185 | + // 应始终使用 GetDpi 方法进行检索。 |
| 186 | + // 有关详细信息,请参阅 DeviceResources.cpp。 |
| 187 | + GetDeviceResources()->SetDpi(sender->LogicalDpi); |
| 188 | + m_main->OnWindowSizeChanged(); |
| 189 | +} |
| 190 | + |
| 191 | +void App::OnOrientationChanged(DisplayInformation^ sender, Object^ args) |
| 192 | +{ |
| 193 | + GetDeviceResources()->SetCurrentOrientation(sender->CurrentOrientation); |
| 194 | + m_main->OnWindowSizeChanged(); |
| 195 | +} |
| 196 | + |
| 197 | +void App::OnDisplayContentsInvalidated(DisplayInformation^ sender, Object^ args) |
| 198 | +{ |
| 199 | + GetDeviceResources()->ValidateDevice(); |
| 200 | +} |
| 201 | + |
| 202 | +std::shared_ptr<DX::DeviceResources> App::GetDeviceResources() |
| 203 | +{ |
| 204 | + if (m_deviceResources != nullptr && m_deviceResources->IsDeviceRemoved()) |
| 205 | + { |
| 206 | + // 必须先释放对现有 D3D 设备的所有引用,然后才能 |
| 207 | + // 创建新设备。 |
| 208 | + |
| 209 | + m_deviceResources = nullptr; |
| 210 | + m_main->OnDeviceRemoved(); |
| 211 | + |
| 212 | +#if defined(_DEBUG) |
| 213 | + ComPtr<IDXGIDebug1> dxgiDebug; |
| 214 | + if (SUCCEEDED(DXGIGetDebugInterface1(0, IID_PPV_ARGS(&dxgiDebug)))) |
| 215 | + { |
| 216 | + dxgiDebug->ReportLiveObjects(DXGI_DEBUG_ALL, DXGI_DEBUG_RLO_FLAGS(DXGI_DEBUG_RLO_SUMMARY | DXGI_DEBUG_RLO_IGNORE_INTERNAL)); |
| 217 | + } |
| 218 | +#endif |
| 219 | + } |
| 220 | + |
| 221 | + if (m_deviceResources == nullptr) |
| 222 | + { |
| 223 | + m_deviceResources = std::make_shared<DX::DeviceResources>(); |
| 224 | + m_deviceResources->SetWindow(CoreWindow::GetForCurrentThread()); |
| 225 | + m_main->CreateRenderers(m_deviceResources); |
| 226 | + } |
| 227 | + return m_deviceResources; |
| 228 | +} |
0 commit comments