core: Define VK_USE_PLATFORM_XCB_KHR before including vkd3d_utils.h.
[vkmodelviewer.git] / Core / GameCore.cpp
blobc4157bff1cba084c897417d2a8106d6ac6e6bd36
1 //
2 // Copyright (c) Microsoft. All rights reserved.
3 // This code is licensed under the MIT License (MIT).
4 // THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
5 // ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
6 // IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
7 // PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
8 //
9 // Developed by Minigraph
11 // Author: James Stanard
14 #include "pch.h"
15 #include "GameCore.h"
16 #include "GraphicsCore.h"
17 #include "SystemTime.h"
18 #include "GameInput.h"
19 #include "BufferManager.h"
20 #include "CommandContext.h"
21 #include "PostEffects.h"
23 #if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
24 #pragma comment(lib, "runtimeobject.lib")
25 #else
26 #include <agile.h>
27 using namespace Windows::ApplicationModel;
28 using namespace Windows::UI::Core;
29 using namespace Windows::UI::ViewManagement;
30 using Windows::ApplicationModel::Core::CoreApplication;
31 using Windows::ApplicationModel::Core::CoreApplicationView;
32 using Windows::ApplicationModel::Activation::IActivatedEventArgs;
33 using Windows::Foundation::TypedEventHandler;
34 #endif
36 namespace Graphics
38 extern ColorBuffer g_GenMipsBuffer;
41 namespace GameCore
43 using namespace Graphics;
44 const bool TestGenerateMips = false;
46 void InitializeApplication( IGameApp& game )
48 Graphics::Initialize();
49 SystemTime::Initialize();
50 GameInput::Initialize();
51 EngineTuning::Initialize();
53 game.Startup();
56 void TerminateApplication( IGameApp& game )
58 game.Cleanup();
60 GameInput::Shutdown();
63 bool UpdateApplication( IGameApp& game )
65 EngineProfiling::Update();
67 float DeltaTime = Graphics::GetFrameTime();
69 GameInput::Update(DeltaTime);
70 EngineTuning::Update(DeltaTime);
72 game.Update(DeltaTime);
73 game.RenderScene();
75 PostEffects::Render();
77 if (TestGenerateMips)
79 GraphicsContext& MipsContext = GraphicsContext::Begin();
81 // Exclude from timings this copy necessary to setup the test
82 MipsContext.TransitionResource(g_SceneColorBuffer, D3D12_RESOURCE_STATE_GENERIC_READ);
83 MipsContext.TransitionResource(g_GenMipsBuffer, D3D12_RESOURCE_STATE_COPY_DEST);
84 MipsContext.CopySubresource(g_GenMipsBuffer, 0, g_SceneColorBuffer, 0);
86 EngineProfiling::BeginBlock(L"GenerateMipMaps()", &MipsContext);
87 g_GenMipsBuffer.GenerateMipMaps(MipsContext);
88 EngineProfiling::EndBlock(&MipsContext);
90 MipsContext.Finish();
93 GraphicsContext& UiContext = GraphicsContext::Begin(L"Render UI");
94 UiContext.TransitionResource(g_OverlayBuffer, D3D12_RESOURCE_STATE_RENDER_TARGET, true);
95 UiContext.ClearColor(g_OverlayBuffer);
96 UiContext.SetRenderTarget(g_OverlayBuffer.GetRTV());
97 UiContext.SetViewportAndScissor(0, 0, g_OverlayBuffer.GetWidth(), g_OverlayBuffer.GetHeight());
98 game.RenderUI(UiContext);
100 EngineTuning::Display( UiContext, 10.0f, 40.0f, 1900.0f, 1040.0f );
102 UiContext.Finish();
104 Graphics::Present();
106 return !game.IsDone();
109 // Default implementation to be overridden by the application
110 bool IGameApp::IsDone( void )
112 return GameInput::IsFirstPressed(GameInput::kKey_escape);
115 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
116 IGameApp* m_game;
117 Platform::Agile<CoreWindow> g_window;
119 ref class MyApplicationView sealed : public Core::IFrameworkView
121 public:
122 MyApplicationView() {}
124 // IFrameworkView Methods.
125 virtual void Initialize(CoreApplicationView^ applicationView);
126 virtual void Load(Platform::String^ entryPoint);
127 virtual void Run(void);
128 virtual void SetWindow(CoreWindow^ window);
129 virtual void Uninitialize(void);
131 protected:
132 // Event Handlers.
133 void OnActivated(Core::CoreApplicationView^ applicationView, Activation::IActivatedEventArgs^ args);
134 void OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args);
135 void OnResuming(Platform::Object^ sender, Platform::Object^ args);
136 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
137 void OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args);
138 void OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args);
139 void OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args);
140 void OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args);
141 void OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args);
142 void OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args);
143 void OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args);
144 #endif
146 private:
147 bool m_windowClosed;
148 bool m_windowVisible;
149 volatile bool m_IsRunning;
150 volatile bool m_IsCapturingPointer;
151 float m_PointerX, m_PointerY;
154 ref class ApplicationViewSource sealed : Core::IFrameworkViewSource
156 public:
157 virtual Core::IFrameworkView^ CreateView()
159 return ref new MyApplicationView();
164 // Called by the system. Perform application initialization here, hooking application wide events, etc.
165 void MyApplicationView::Initialize(CoreApplicationView^ applicationView)
167 applicationView->Activated += ref new TypedEventHandler<CoreApplicationView^, IActivatedEventArgs^>(this, &MyApplicationView::OnActivated);
170 // Called when we are provided a window.
171 void MyApplicationView::SetWindow(CoreWindow^ window)
173 // We record the window pointer now, but you can also call this function to retrieve it:
174 // CoreWindow::GetForCurrentThread()
175 g_window = window;
177 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
178 window->SizeChanged += ref new TypedEventHandler<CoreWindow^, WindowSizeChangedEventArgs^>(this, &MyApplicationView::OnWindowSizeChanged);
179 window->VisibilityChanged += ref new TypedEventHandler<CoreWindow^, VisibilityChangedEventArgs^>(this, &MyApplicationView::OnVisibilityChanged);
180 window->Closed += ref new TypedEventHandler<CoreWindow^, CoreWindowEventArgs^>(this, &MyApplicationView::OnWindowClosed);
181 window->KeyDown += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &MyApplicationView::OnKeyDown);
182 window->KeyUp += ref new TypedEventHandler<CoreWindow^, KeyEventArgs^>(this, &MyApplicationView::OnKeyUp);
183 window->PointerPressed += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &MyApplicationView::OnPointerPressed);
184 window->PointerMoved += ref new TypedEventHandler<CoreWindow^, PointerEventArgs^>(this, &MyApplicationView::OnPointerMoved);
185 #endif
188 void MyApplicationView::Load(Platform::String^ entryPoint)
190 InitializeApplication(*m_game);
193 // Called by the system after initialization is complete. This implements the traditional game loop.
194 void MyApplicationView::Run()
196 while (m_IsRunning)
198 // ProcessEvents will throw if the process is exiting, allowing us to break out of the loop. This will be
199 // cleaned up when we get proper process lifetime management in a future release.
200 g_window->Dispatcher->ProcessEvents(CoreProcessEventsOption::ProcessAllIfPresent);
202 m_IsRunning = UpdateApplication(*m_game);
206 void MyApplicationView::Uninitialize()
208 Graphics::Terminate();
209 TerminateApplication(*m_game);
210 Graphics::Shutdown();
213 // Called when the application is activated. For now, there is just one activation kind - Launch.
214 void MyApplicationView::OnActivated(CoreApplicationView^ applicationView, IActivatedEventArgs^ args)
216 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
217 float DpiScale = 96.0f / Windows::Graphics::Display::DisplayInformation::GetForCurrentView()->LogicalDpi;
218 ApplicationView::PreferredLaunchWindowingMode = ApplicationViewWindowingMode::PreferredLaunchViewSize;
219 Windows::Foundation::Size DesiredSize(Graphics::g_DisplayWidth * DpiScale, Graphics::g_DisplayHeight * DpiScale);
220 ApplicationView::PreferredLaunchViewSize = DesiredSize;
221 ApplicationView::GetForCurrentView()->TryResizeView(DesiredSize);
222 #endif
224 m_IsRunning = true;
225 m_IsCapturingPointer = false;
226 g_window->Activate();
229 void MyApplicationView::OnSuspending(Platform::Object^ sender, SuspendingEventArgs^ args) {}
230 void MyApplicationView::OnResuming(Platform::Object^ sender, Platform::Object^ args) {}
232 #if !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)
233 void MyApplicationView::OnWindowSizeChanged(CoreWindow^ sender, WindowSizeChangedEventArgs^ args)
235 Graphics::Resize((uint32_t)sender->Bounds.Width, (uint32_t)sender->Bounds.Height);
238 void MyApplicationView::OnWindowClosed(CoreWindow^ sender, CoreWindowEventArgs^ args)
240 m_IsRunning = false;
243 void MyApplicationView::OnVisibilityChanged(CoreWindow^ sender, VisibilityChangedEventArgs^ args) {}
245 void MyApplicationView::OnPointerPressed(CoreWindow^ sender, PointerEventArgs^ args)
247 //DEBUGPRINT("Pointer pressed (%f, %f)", args->CurrentPoint->RawPosition.X, args->CurrentPoint->RawPosition.Y);
248 if (m_IsCapturingPointer)
250 g_window->ReleasePointerCapture();
251 m_IsCapturingPointer = false;
252 g_window->PointerCursor = ref new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Arrow, 0);
253 //DEBUGPRINT("Pointer released");
255 else
257 g_window->SetPointerCapture();
258 m_IsCapturingPointer = true;
259 g_window->PointerCursor = ref new Windows::UI::Core::CoreCursor(Windows::UI::Core::CoreCursorType::Hand, 0);
260 m_PointerX = args->CurrentPoint->RawPosition.X;
261 m_PointerY = args->CurrentPoint->RawPosition.Y;
262 //DEBUGPRINT("Pointer captured");
266 void MyApplicationView::OnPointerMoved(CoreWindow^ sender, PointerEventArgs^ args)
268 if (!m_IsCapturingPointer)
269 return;
271 float OldX = m_PointerX;
272 float OldY = m_PointerY;
274 m_PointerX = args->CurrentPoint->RawPosition.X;
275 m_PointerY = args->CurrentPoint->RawPosition.Y;
277 //DEBUGPRINT("Pointer moved (%f, %f)", m_PointerX, m_PointerY);
278 //DEBUGPRINT("Pointer was (%f, %f)", OldX, OldY);
279 //GameInput::SetMouseMovement(m_PointerX)
282 void MyApplicationView::OnKeyDown(CoreWindow^ sender, KeyEventArgs^ args)
284 GameInput::SetKeyState(args->VirtualKey, true);
287 void MyApplicationView::OnKeyUp(CoreWindow^ sender, KeyEventArgs^ args)
289 GameInput::SetKeyState(args->VirtualKey, false);
291 #endif
293 void RunApplication(IGameApp &app, const char *className)
295 m_game = &app;
296 (void)className;
297 auto applicationViewSource = ref new ApplicationViewSource();
298 CoreApplication::Run(applicationViewSource);
301 #else // Win32
303 struct port_window *window = nullptr;
304 struct port port = {};
306 static void idle(struct port *port, void *user_data)
308 if (!UpdateApplication(*(IGameApp *)user_data))
309 port_window_destroy(window);
312 void RunApplication(IGameApp &app, const char *className)
314 ASSERT(port_init(&port, &app));
315 ASSERT(window = port_window_create(&port, className, g_DisplayWidth, g_DisplayHeight, &app));
316 InitializeApplication(app);
318 port_set_idle_func(&port, idle);
319 port_process_events(&port);
321 Graphics::Terminate();
322 TerminateApplication(app);
323 Graphics::Shutdown();
325 port_cleanup(&port);
327 #endif