summaryrefslogtreecommitdiffstats
path: root/Projects/Asteroids/src/WinWrapper.cpp
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2017-05-20 20:20:23 +0000
committerEgor Yusov <egor.yusov@gmail.com>2017-05-20 20:20:23 +0000
commitcdd751dc2f5bf0851c795587aab4fd547e95b6a8 (patch)
treec20f440a9a092ec8f655e38f30cab522a4933f93 /Projects/Asteroids/src/WinWrapper.cpp
parentUpdated submodules (diff)
downloadDiligentEngine-cdd751dc2f5bf0851c795587aab4fd547e95b6a8.tar.gz
DiligentEngine-cdd751dc2f5bf0851c795587aab4fd547e95b6a8.zip
Added asteroids sample
Diffstat (limited to 'Projects/Asteroids/src/WinWrapper.cpp')
-rw-r--r--Projects/Asteroids/src/WinWrapper.cpp616
1 files changed, 616 insertions, 0 deletions
diff --git a/Projects/Asteroids/src/WinWrapper.cpp b/Projects/Asteroids/src/WinWrapper.cpp
new file mode 100644
index 0000000..ffb0f6d
--- /dev/null
+++ b/Projects/Asteroids/src/WinWrapper.cpp
@@ -0,0 +1,616 @@
+// Copyright 2014 Intel Corporation All Rights Reserved
+//
+// Intel makes no representations about the suitability of this software for any purpose.
+// THIS SOFTWARE IS PROVIDED ""AS IS."" INTEL SPECIFICALLY DISCLAIMS ALL WARRANTIES,
+// EXPRESS OR IMPLIED, AND ALL LIABILITY, INCLUDING CONSEQUENTIAL AND OTHER INDIRECT DAMAGES,
+// FOR THE USE OF THIS SOFTWARE, INCLUDING LIABILITY FOR INFRINGEMENT OF ANY PROPRIETARY
+// RIGHTS, AND INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+// Intel does not assume any responsibility for any errors which may appear in this software
+// nor any responsibility to update it.
+
+#define WIN32_LEAN_AND_MEAN
+#include <sdkddkver.h>
+#include <windows.h>
+#include <windowsx.h>
+#include <shellapi.h> // must be after windows.h
+#include <ShellScalingApi.h>
+#include <interactioncontext.h>
+#include <mmsystem.h>
+#include <map>
+#include <vector>
+#include <iostream>
+
+#include "asteroids_d3d11.h"
+#include "asteroids_d3d12.h"
+#include "asteroids_DE.h"
+#include "camera.h"
+#include "gui.h"
+
+using namespace DirectX;
+
+namespace {
+
+// Global demo state
+Settings gSettings;
+OrbitCamera gCamera;
+
+IDXGIFactory2* gDXGIFactory = nullptr;
+
+AsteroidsD3D11::Asteroids* gWorkloadD3D11 = nullptr;
+AsteroidsD3D12::Asteroids* gWorkloadD3D12 = nullptr;
+AsteroidsDE::Asteroids* gWorkloadDE = nullptr;
+bool gd3d11Available = false;
+bool gd3d12Available = false;
+Settings::RenderMode gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1);
+
+GUI gGUI;
+GUIText* gFPSControl;
+
+enum
+{
+ basicStyle = WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_VISIBLE,
+ windowedStyle = basicStyle | WS_OVERLAPPEDWINDOW,
+ fullscreenStyle = basicStyle
+};
+
+bool CheckDll(char const* dllName)
+{
+ auto hModule = LoadLibrary(dllName);
+ if (hModule == NULL) {
+ return false;
+ }
+ FreeLibrary(hModule);
+ return true;
+}
+
+
+UINT SetupDPI()
+{
+ // Just do system DPI awareness for now for simplicity... scale the 3D content
+ SetProcessDpiAwareness(PROCESS_SYSTEM_DPI_AWARE);
+
+ UINT dpiX = 0, dpiY;
+ POINT pt = {1, 1};
+ auto hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST);
+ if (SUCCEEDED(GetDpiForMonitor(hMonitor, MDT_EFFECTIVE_DPI, &dpiX, &dpiY))) {
+ return dpiX;
+ } else {
+ return 96; // default
+ }
+}
+
+
+void ResetCameraView()
+{
+ auto center = XMVectorSet(0.0f, -0.4f*SIM_DISC_RADIUS, 0.0f, 0.0f);
+ auto radius = SIM_ORBIT_RADIUS + SIM_DISC_RADIUS + 10.f;
+ auto minRadius = SIM_ORBIT_RADIUS - 3.0f * SIM_DISC_RADIUS;
+ auto maxRadius = SIM_ORBIT_RADIUS + 3.0f * SIM_DISC_RADIUS;
+ auto longAngle = 4.50f;
+ auto latAngle = 1.45f;
+ gCamera.View(center, radius, minRadius, maxRadius, longAngle, latAngle);
+}
+
+void ToggleFullscreen(HWND hWnd)
+{
+ static WINDOWPLACEMENT prevPlacement = { sizeof(prevPlacement) };
+ DWORD dwStyle = (DWORD)GetWindowLongPtr(hWnd, GWL_STYLE);
+ if ((dwStyle & windowedStyle) == windowedStyle)
+ {
+ MONITORINFO mi = { sizeof(mi) };
+ if (GetWindowPlacement(hWnd, &prevPlacement) &&
+ GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTOPRIMARY), &mi))
+ {
+ SetWindowLong(hWnd, GWL_STYLE, fullscreenStyle);
+ SetWindowPos(hWnd, HWND_TOP,
+ mi.rcMonitor.left, mi.rcMonitor.top,
+ mi.rcMonitor.right - mi.rcMonitor.left,
+ mi.rcMonitor.bottom - mi.rcMonitor.top,
+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+ }
+ } else {
+ SetWindowLong(hWnd, GWL_STYLE, windowedStyle);
+ SetWindowPlacement(hWnd, &prevPlacement);
+ SetWindowPos(hWnd, NULL, 0, 0, 0, 0,
+ SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
+ SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
+ }
+}
+
+
+} // namespace
+
+
+
+LRESULT CALLBACK WindowProc(
+ HWND hWnd,
+ UINT message,
+ WPARAM wParam,
+ LPARAM lParam)
+{
+ switch (message) {
+ case WM_DESTROY:
+ PostQuitMessage(0);
+ return 0;
+
+ case WM_SIZE: {
+ UINT ww = LOWORD(lParam);
+ UINT wh = HIWORD(lParam);
+
+ // Ignore resizing to minimized
+ if (ww == 0 || wh == 0) return 0;
+
+ gSettings.windowWidth = (int)ww;
+ gSettings.windowHeight = (int)wh;
+ gSettings.renderWidth = (UINT)(double(gSettings.windowWidth) * gSettings.renderScale);
+ gSettings.renderHeight = (UINT)(double(gSettings.windowHeight) * gSettings.renderScale);
+
+ // Update camera projection
+ float aspect = (float)gSettings.renderWidth / (float)gSettings.renderHeight;
+ gCamera.Projection(XM_PIDIV2 * 0.8f * 3 / 2, aspect);
+
+ // Resize currently active swap chain
+ switch (gSettings.mode)
+ {
+ case Settings::RenderMode::NativeD3D11:
+ if(gWorkloadD3D11)
+ gWorkloadD3D11->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight);
+ break;
+
+ case Settings::RenderMode::NativeD3D12:
+ if(gWorkloadD3D12)
+ gWorkloadD3D12->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight);
+ break;
+
+ case Settings::RenderMode::DiligentD3D11:
+ case Settings::RenderMode::DiligentD3D12:
+ case Settings::RenderMode::DiligentGL:
+ if(gWorkloadDE)
+ gWorkloadDE->ResizeSwapChain(hWnd, gSettings.renderWidth, gSettings.renderHeight);
+ break;
+ }
+
+ return 0;
+ }
+
+ case WM_KEYDOWN:
+ if (lParam & (1 << 30)) {
+ // Ignore repeats
+ return 0;
+ }
+ switch (wParam) {
+ case VK_SPACE:
+ gSettings.animate = !gSettings.animate;
+ std::cout << "Animate: " << gSettings.animate << std::endl;
+ return 0;
+
+ /* Disabled for demo setup */
+ case 'V':
+ gSettings.vsync = !gSettings.vsync;
+ std::cout << "Vsync: " << gSettings.vsync << std::endl;
+ return 0;
+ case 'M':
+ gSettings.multithreadedRendering = !gSettings.multithreadedRendering;
+ std::cout << "Multithreaded Rendering: " << gSettings.multithreadedRendering << std::endl;
+ return 0;
+ case 'I':
+ gSettings.executeIndirect = !gSettings.executeIndirect;
+ std::cout << "ExecuteIndirect Rendering: " << gSettings.executeIndirect << std::endl;
+ return 0;
+ case 'S':
+ gSettings.submitRendering = !gSettings.submitRendering;
+ std::cout << "Submit Rendering: " << gSettings.submitRendering << std::endl;
+ return 0;
+
+ case VK_ADD:
+ case VK_OEM_PLUS:
+ gSettings.numThreads = std::min(gSettings.numThreads+1, 16);
+ gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1);
+ return 0;
+ case VK_SUBTRACT:
+ case VK_OEM_MINUS:
+ gSettings.numThreads = std::max(gSettings.numThreads-1, 2);
+ gLastFrameRenderMode = static_cast<Settings::RenderMode>(-1);
+ return 0;
+
+ case '1': gSettings.mode = gd3d11Available ? Settings::RenderMode::NativeD3D11 : gSettings.mode; return 0;
+ case '2': gSettings.mode = gd3d12Available ? Settings::RenderMode::NativeD3D12 : gSettings.mode; return 0;
+ case '3': gSettings.mode = gd3d11Available ? Settings::RenderMode::DiligentD3D11 : gSettings.mode; return 0;
+ case '4': gSettings.mode = gd3d12Available ? Settings::RenderMode::DiligentD3D12 : gSettings.mode; return 0;
+ case '5': gSettings.mode = Settings::RenderMode::DiligentGL; return 0;
+
+ case VK_ESCAPE:
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ return 0;
+ } // Switch on key code
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if (lParam & (1 << 30)) {
+ // Ignore repeats
+ return 0;
+ }
+ switch (wParam) {
+ case VK_RETURN:
+ ToggleFullscreen(hWnd);
+ break;
+ }
+ return 0;
+
+ case WM_MOUSEWHEEL: {
+ auto delta = GET_WHEEL_DELTA_WPARAM(wParam);
+ gCamera.ZoomRadius(-0.07f * delta);
+ return 0;
+ }
+
+ case WM_POINTERDOWN:
+ case WM_POINTERUPDATE:
+ case WM_POINTERUP: {
+ auto pointerId = GET_POINTERID_WPARAM(wParam);
+ POINTER_INFO pointerInfo;
+ if (GetPointerInfo(pointerId, &pointerInfo)) {
+ if (message == WM_POINTERDOWN) {
+ // Compute pointer position in render units
+ POINT p = pointerInfo.ptPixelLocation;
+ ScreenToClient(hWnd, &p);
+ RECT clientRect;
+ GetClientRect(hWnd, &clientRect);
+ p.x = p.x * gSettings.renderWidth / (clientRect.right - clientRect.left);
+ p.y = p.y * gSettings.renderHeight / (clientRect.bottom - clientRect.top);
+
+ auto guiControl = gGUI.HitTest(p.x, p.y);
+ if (guiControl == gFPSControl) {
+ gSettings.lockFrameRate = !gSettings.lockFrameRate;
+ } else { // Camera manipulation
+ gCamera.AddPointer(pointerId);
+ }
+ }
+
+ // Otherwise send it to the camera controls
+ gCamera.ProcessPointerFrames(pointerId, &pointerInfo);
+ if (message == WM_POINTERUP) gCamera.RemovePointer(pointerId);
+ }
+ return 0;
+ }
+
+ default:
+ return DefWindowProc(hWnd, message, wParam, lParam);
+ }
+}
+
+int InitWorkload(HWND hWnd, AsteroidsSimulation &asteroids)
+{
+ delete gWorkloadD3D11;
+ gWorkloadD3D11 = nullptr;
+ delete gWorkloadD3D12;
+ gWorkloadD3D12 = nullptr;
+ delete gWorkloadDE;
+ gWorkloadDE = nullptr;
+ switch (gSettings.mode)
+ {
+ case Settings::RenderMode::NativeD3D11:
+ if (gd3d11Available) {
+ gWorkloadD3D11 = new AsteroidsD3D11::Asteroids(&asteroids, &gGUI, gSettings.warp);
+ }
+
+ gWorkloadD3D11->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight);
+ break;
+
+ case Settings::RenderMode::NativeD3D12:
+ if (gd3d12Available) {
+ // If requested, enumerate the warp adapter
+ // TODO: Allow picking from multiple hardware adapters
+ IDXGIAdapter1* adapter = nullptr;
+
+ if (gSettings.warp) {
+ IDXGIFactory4* DXGIFactory4 = nullptr;
+ if (FAILED(gDXGIFactory->QueryInterface(&DXGIFactory4))) {
+ fprintf(stderr, "error: WARP requires IDXGIFactory4 interface which is not present on this system!\n");
+ return -1;
+ }
+
+ auto hr = DXGIFactory4->EnumWarpAdapter(IID_PPV_ARGS(&adapter));
+ DXGIFactory4->Release();
+
+ if (FAILED(hr)) {
+ fprintf(stderr, "error: WARP adapter not present on this system!\n");
+ return -1;
+ }
+ }
+
+ gWorkloadD3D12 = new AsteroidsD3D12::Asteroids(&asteroids, &gGUI, gSettings.numThreads, adapter);
+ }
+
+ gWorkloadD3D12->ResizeSwapChain(gDXGIFactory, hWnd, gSettings.renderWidth, gSettings.renderHeight);
+ break;
+
+ case Settings::RenderMode::DiligentD3D11:
+ gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::D3D11);
+ break;
+
+ case Settings::RenderMode::DiligentD3D12:
+ gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::D3D12);
+ break;
+
+ case Settings::RenderMode::DiligentGL:
+ gWorkloadDE = new AsteroidsDE::Asteroids(gSettings.numThreads, &asteroids, &gGUI, hWnd, Diligent::DeviceType::OpenGL);
+ break;
+ }
+
+ return 0;
+}
+
+int main(int argc, char** argv)
+{
+#if defined(_DEBUG) || defined(DEBUG)
+ _CrtSetDbgFlag( _CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF );
+#endif
+
+ gd3d11Available = CheckDll("d3d11.dll");
+ gd3d12Available = CheckDll("d3d12.dll");
+
+ // Must be done before any windowing-system-like things or else virtualization will kick in
+ auto dpi = SetupDPI();
+ // By default render at the lower resolution and scale up based on system settings
+ gSettings.renderScale = 96.0 / double(dpi);
+
+ // Scale default window size based on dpi
+ gSettings.windowWidth *= dpi / 96;
+ gSettings.windowHeight *= dpi / 96;
+
+ for (int a = 1; a < argc; ++a) {
+ if (_stricmp(argv[a], "-close_after") == 0 && a + 1 < argc) {
+ gSettings.closeAfterSeconds = atof(argv[++a]);
+ } else if (_stricmp(argv[a], "-nod3d11") == 0) {
+ gd3d11Available = false;
+ } else if (_stricmp(argv[a], "-warp") == 0) {
+ gSettings.warp = true;
+ } else if (_stricmp(argv[a], "-nod3d12") == 0) {
+ gd3d12Available = false;
+ } else if (_stricmp(argv[a], "-indirect") == 0) {
+ gSettings.executeIndirect = true;
+ } else if (_stricmp(argv[a], "-fullscreen") == 0) {
+ gSettings.windowed = false;
+ } else if (_stricmp(argv[a], "-window") == 0 && a + 2 < argc) {
+ gSettings.windowWidth = atoi(argv[++a]);
+ gSettings.windowHeight = atoi(argv[++a]);
+ } else if (_stricmp(argv[a], "-render_scale") == 0 && a + 1 < argc) {
+ gSettings.renderScale = atof(argv[++a]);
+ } else if (_stricmp(argv[a], "-locked_fps") == 0 && a + 1 < argc) {
+ gSettings.lockedFrameRate = atoi(argv[++a]);
+ } else if (_stricmp(argv[a], "-threads") == 0 && a + 1 < argc) {
+ gSettings.numThreads = atoi(argv[++a]);
+ } else {
+ fprintf(stderr, "error: unrecognized argument '%s'\n", argv[a]);
+ fprintf(stderr, "usage: asteroids_d3d12 [options]\n");
+ fprintf(stderr, "options:\n");
+ fprintf(stderr, " -close_after [seconds]\n");
+ fprintf(stderr, " -nod3d11\n");
+ fprintf(stderr, " -nod3d12\n");
+ fprintf(stderr, " -fullscreen\n");
+ fprintf(stderr, " -window [width] [height]\n");
+ fprintf(stderr, " -render_scale [scale]\n");
+ fprintf(stderr, " -locked_fps [fps]\n");
+ fprintf(stderr, " -warp\n");
+ return -1;
+ }
+ }
+
+ if (gSettings.numThreads == 0)
+ {
+ gSettings.numThreads = std::max(std::thread::hardware_concurrency()-1, 2u);
+ }
+
+ //if (!d3d11Available && !d3d12Available) {
+ // fprintf(stderr, "error: neither D3D11 nor D3D12 available.\n");
+ // return -1;
+ //}
+
+ // DXGI Factory
+ ThrowIfFailed(CreateDXGIFactory2(0, IID_PPV_ARGS(&gDXGIFactory)));
+
+ // Setup GUI
+ gFPSControl = gGUI.AddText(150, 10);
+
+ ResetCameraView();
+ // Camera projection set up in WM_SIZE
+
+ AsteroidsSimulation asteroids(1337, NUM_ASTEROIDS, NUM_UNIQUE_MESHES, MESH_MAX_SUBDIV_LEVELS, NUM_UNIQUE_TEXTURES);
+
+
+ gSettings.mode = Settings::RenderMode::DiligentD3D12;
+
+
+ // init window class
+ WNDCLASSEX windowClass;
+ ZeroMemory(&windowClass, sizeof(WNDCLASSEX));
+ windowClass.cbSize = sizeof(WNDCLASSEX);
+ windowClass.style = CS_HREDRAW | CS_VREDRAW;
+ windowClass.lpfnWndProc = WindowProc;
+ windowClass.hInstance = GetModuleHandle(NULL);
+ windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
+ windowClass.lpszClassName = "AsteroidsD3D12WindowClass";
+ RegisterClassEx(&windowClass);
+
+ RECT windowRect = { 0, 0, gSettings.windowWidth, gSettings.windowHeight };
+ AdjustWindowRect(&windowRect, windowedStyle, FALSE);
+
+ // create the window and store a handle to it
+ auto hWnd = CreateWindowEx(
+ WS_EX_APPWINDOW,
+ "AsteroidsD3D12WindowClass",
+ "Asteroids",
+ windowedStyle,
+ 0, // CW_USE_DEFAULT
+ 0, // CW_USE_DEFAULT
+ windowRect.right - windowRect.left,
+ windowRect.bottom - windowRect.top,
+ NULL,
+ NULL,
+ windowClass.hInstance,
+ NULL);
+
+ if (!gSettings.windowed) {
+ ToggleFullscreen(hWnd);
+ }
+
+ SetForegroundWindow(hWnd);
+
+ // Initialize performance counters
+ UINT64 perfCounterFreq = 0;
+ UINT64 lastPerfCount = 0;
+ QueryPerformanceFrequency((LARGE_INTEGER*)&perfCounterFreq);
+ QueryPerformanceCounter((LARGE_INTEGER*)&lastPerfCount);
+
+ // main loop
+ double elapsedTime = 0.0;
+ double frameTime = 0.0;
+ int lastMouseX = 0;
+ int lastMouseY = 0;
+ POINTER_INFO pointerInfo = {};
+
+ timeBeginPeriod(1);
+ EnableMouseInPointer(TRUE);
+
+ float filteredUpdateTime = 0.0f;
+ float filteredRenderTime = 0.0f;
+ float filteredFrameTime = 0.0f;
+ for (;;)
+ {
+ MSG msg = {};
+ while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
+ if (msg.message == WM_QUIT) {
+ // Cleanup
+ delete gWorkloadD3D11;
+ delete gWorkloadD3D12;
+ delete gWorkloadDE;
+ SafeRelease(&gDXGIFactory);
+ timeEndPeriod(1);
+ EnableMouseInPointer(FALSE);
+ return (int)msg.wParam;
+ };
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ // If we swap to a new API we need to recreate swap chains
+ if (gLastFrameRenderMode != gSettings.mode) {
+ InitWorkload(hWnd, asteroids);
+ gLastFrameRenderMode = gSettings.mode;
+ }
+
+ // Still need to process inertia even when no interaction is happening
+ gCamera.ProcessInertia();
+
+ // In D3D12 we'll wait on the GPU before taking the timestamp (more consistent)
+ if (gSettings.mode == Settings::RenderMode::NativeD3D12) {
+ gWorkloadD3D12->WaitForReadyToRender();
+ }
+
+ // Get time delta
+ UINT64 count;
+ QueryPerformanceCounter((LARGE_INTEGER*)&count);
+ auto rawFrameTime = (double)(count - lastPerfCount) / perfCounterFreq;
+ elapsedTime += rawFrameTime;
+ lastPerfCount = count;
+
+ // Maintaining absolute time sync is not important in this demo so we can err on the "smoother" side
+ double alpha = 0.2f;
+ frameTime = alpha * rawFrameTime + (1.0f - alpha) * frameTime;
+
+ // Update GUI
+ {
+ const char *ModeStr = nullptr;
+ float updateTime = 0;
+ float renderTime = 0;
+ switch (gSettings.mode)
+ {
+ case Settings::RenderMode::NativeD3D11:
+ ModeStr = "Native D3D11";
+ gWorkloadD3D11->GetPerfCounters(updateTime, renderTime);
+ break;
+
+ case Settings::RenderMode::NativeD3D12:
+ ModeStr = "Native D3D12";
+ gWorkloadD3D12->GetPerfCounters(updateTime, renderTime);
+ break;
+
+ case Settings::RenderMode::DiligentD3D11:
+ ModeStr = "Diligent D3D11";
+ gWorkloadDE->GetPerfCounters(updateTime, renderTime);
+ break;
+
+ case Settings::RenderMode::DiligentD3D12:
+ ModeStr = "Diligent D3D12";
+ gWorkloadDE->GetPerfCounters(updateTime, renderTime);
+ break;
+
+ case Settings::RenderMode::DiligentGL:
+ ModeStr = "Diligent GL";
+ gWorkloadDE->GetPerfCounters(updateTime, renderTime);
+ break;
+ }
+ float filterScale = 0.05f;
+ filteredUpdateTime = filteredUpdateTime * (1.f - filterScale) + filterScale * updateTime;
+ filteredRenderTime = filteredRenderTime * (1.f - filterScale) + filterScale * renderTime;
+ filteredFrameTime = filteredFrameTime * (1.f - filterScale) + filterScale * (float)frameTime;
+
+ char buffer[256];
+ sprintf(buffer, "Asteroids %s (%dt) - %4.2f ms (%4.2f ms / %4.2f ms)", ModeStr, gSettings.multithreadedRendering ? gSettings.numThreads : 1,
+ 1000.f * filteredFrameTime, 1000.f * filteredUpdateTime, 1000.f * filteredRenderTime);
+
+ SetWindowText(hWnd, buffer);
+
+ if (gSettings.lockFrameRate) {
+ sprintf(buffer, "(Locked)");
+ } else {
+ sprintf(buffer, "%.0f fps", 1.0f / filteredFrameTime);
+ }
+ gFPSControl->Text(buffer);
+ }
+
+ switch (gSettings.mode)
+ {
+ case Settings::RenderMode::NativeD3D11:
+ if(gWorkloadD3D11)
+ gWorkloadD3D11->Render((float)frameTime, gCamera, gSettings);
+ break;
+
+ case Settings::RenderMode::NativeD3D12:
+ if(gWorkloadD3D12)
+ gWorkloadD3D12->Render((float)frameTime, gCamera, gSettings);
+ break;
+
+ case Settings::RenderMode::DiligentD3D11:
+ case Settings::RenderMode::DiligentD3D12:
+ case Settings::RenderMode::DiligentGL:
+ if(gWorkloadDE)
+ gWorkloadDE->Render((float)frameTime, gCamera, gSettings);
+ break;
+ }
+
+ if (gSettings.lockFrameRate) {
+
+ UINT64 afterRenderCount;
+ QueryPerformanceCounter((LARGE_INTEGER*)&afterRenderCount);
+ double renderTime = (double)(afterRenderCount - count) / perfCounterFreq;
+
+ double targetRenderTime = 1.0 / double(gSettings.lockedFrameRate);
+ double deltaMs = (targetRenderTime - renderTime) * 1000.0;
+ if (deltaMs > 1.0) {
+ Sleep((DWORD)deltaMs);
+ }
+
+ }
+
+ // All done?
+ if (gSettings.closeAfterSeconds > 0.0 && elapsedTime > gSettings.closeAfterSeconds) {
+ SendMessage(hWnd, WM_CLOSE, 0, 0);
+ break;
+ }
+ }
+
+ // Shouldn't get here
+ return 1;
+}