aboutsummaryrefslogtreecommitdiff
path: root/app/source/Cplt/Entrypoint/Backend_DirectX11.cpp
diff options
context:
space:
mode:
authorrtk0c <[email protected]>2022-06-30 21:38:53 -0700
committerrtk0c <[email protected]>2022-06-30 21:38:53 -0700
commit7fe47a9d5b1727a61dc724523b530762f6d6ba19 (patch)
treee95be6e66db504ed06d00b72c579565bab873277 /app/source/Cplt/Entrypoint/Backend_DirectX11.cpp
parent2cf952088d375ac8b2f45b144462af0953436cff (diff)
Restructure project
Diffstat (limited to 'app/source/Cplt/Entrypoint/Backend_DirectX11.cpp')
-rw-r--r--app/source/Cplt/Entrypoint/Backend_DirectX11.cpp250
1 files changed, 250 insertions, 0 deletions
diff --git a/app/source/Cplt/Entrypoint/Backend_DirectX11.cpp b/app/source/Cplt/Entrypoint/Backend_DirectX11.cpp
new file mode 100644
index 0000000..4dc33f7
--- /dev/null
+++ b/app/source/Cplt/Entrypoint/Backend_DirectX11.cpp
@@ -0,0 +1,250 @@
+#include "Backend.hpp"
+
+#if BUILD_CORE_WITH_DX11_BACKEND
+# include <backend/imgui_impl_dx11.h>
+# include <backend/imgui_impl_dx11.cpp>
+# include <stdexcept>
+# include <d3d11.h>
+# include <tchar.h>
+# include <backend/imgui_impl_win32.h>
+
+// Forward declare message handler from imgui_impl_win32.cpp
+extern IMGUI_IMPL_API LRESULT ImGui_ImplWin32_WndProcHandler(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
+
+class DirectX11Backend : public RenderingBackend
+{
+private:
+ HWND hWnd;
+ WNDCLASSEX wc;
+
+ ID3D11Device* mD3dDevice = nullptr;
+ ID3D11DeviceContext* mD3dDeviceContext = nullptr;
+ IDXGISwapChain* mSwapChain = nullptr;
+ ID3D11RenderTargetView* mMainRenderTargetView = nullptr;
+
+public:
+ DirectX11Backend()
+ {
+ ImGui_ImplWin32_EnableDpiAwareness();
+
+ wc.cbSize = sizeof(WNDCLASSEX);
+ wc.style = CS_CLASSDC;
+ wc.lpfnWndProc = &StaticWndProc;
+ wc.cbClsExtra = 0L;
+ wc.cbWndExtra = 0L;
+ wc.hInstance = GetModuleHandle(nullptr);
+ wc.hIcon = nullptr;
+ wc.hCursor = nullptr;
+ wc.hbrBackground = nullptr;
+ wc.lpszMenuName = nullptr;
+ wc.lpszClassName = _T("Cplt");
+ wc.hIconSm = nullptr;
+ ::RegisterClassEx(&wc);
+
+ hWnd = ::CreateWindow(
+ wc.lpszClassName,
+ _T("Cplt main window"),
+ WS_OVERLAPPEDWINDOW,
+ /* x */ 100,
+ /* y */ 100,
+ /* window width */ 1280,
+ /* window height */ 800,
+ nullptr,
+ nullptr,
+ wc.hInstance,
+ this);
+
+ if (!CreateDeviceD3D()) {
+ CleanupDeviceD3D();
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ throw std::runtime_error("Failed to create d3d device.");
+ }
+
+ ::ShowWindow(hWnd, SW_SHOWDEFAULT);
+ ::UpdateWindow(hWnd);
+
+ IMGUI_CHECKVERSION();
+ ImGui::CreateContext();
+
+ ImGui_ImplWin32_Init(hWnd);
+ ImGui_ImplDX11_Init(mD3dDevice, mD3dDeviceContext);
+ }
+
+ virtual ~DirectX11Backend()
+ {
+ ImGui_ImplDX11_Shutdown();
+ ImGui_ImplWin32_Shutdown();
+ ImGui::DestroyContext();
+
+ CleanupDeviceD3D();
+ ::DestroyWindow(hWnd);
+ ::UnregisterClass(wc.lpszClassName, wc.hInstance);
+ }
+
+ virtual void RunUntilWindowClose(void (*windowContent)())
+ {
+ while (true) {
+ MSG msg;
+ bool done = false;
+ while (::PeekMessage(&msg, nullptr, 0U, 0U, PM_REMOVE)) {
+ ::TranslateMessage(&msg);
+ ::DispatchMessage(&msg);
+ if (msg.message == WM_QUIT) {
+ done = true;
+ }
+ }
+ if (done) break;
+
+ ImGui_ImplDX11_NewFrame();
+ ImGui_ImplWin32_NewFrame();
+ ImGui::NewFrame();
+
+ windowContent();
+
+ ImGui::Render();
+ const ImVec4 kClearColor = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
+ const float kClearColorWithAlpha[4] = { kClearColor.x * kClearColor.w, kClearColor.y * kClearColor.w, kClearColor.z * kClearColor.w, kClearColor.w };
+ mD3dDeviceContext->OMSetRenderTargets(1, &mMainRenderTargetView, nullptr);
+ mD3dDeviceContext->ClearRenderTargetView(mMainRenderTargetView, kClearColorWithAlpha);
+ ImGui_ImplDX11_RenderDrawData(ImGui::GetDrawData());
+
+ mSwapChain->Present(1, 0); // Present with vsync
+ }
+ }
+
+private:
+ bool CreateDeviceD3D()
+ {
+ // Setup swap chain
+ DXGI_SWAP_CHAIN_DESC sd;
+ ZeroMemory(&sd, sizeof(sd));
+ sd.BufferCount = 2;
+ sd.BufferDesc.Width = 0;
+ sd.BufferDesc.Height = 0;
+ sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+ sd.BufferDesc.RefreshRate.Numerator = 60;
+ sd.BufferDesc.RefreshRate.Denominator = 1;
+ sd.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
+ sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
+ sd.OutputWindow = hWnd;
+ sd.SampleDesc.Count = 1;
+ sd.SampleDesc.Quality = 0;
+ sd.Windowed = TRUE;
+ sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
+
+ UINT createDeviceFlags = 0;
+ //createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ D3D_FEATURE_LEVEL featureLevel;
+ const D3D_FEATURE_LEVEL featureLevelArray[2] = {
+ D3D_FEATURE_LEVEL_11_0,
+ D3D_FEATURE_LEVEL_10_0,
+ };
+ if (D3D11CreateDeviceAndSwapChain(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, createDeviceFlags, featureLevelArray, 2, D3D11_SDK_VERSION, &sd, &mSwapChain, &mD3dDevice, &featureLevel, &mD3dDeviceContext) != S_OK) {
+ return false;
+ }
+
+ CreateRenderTarget();
+ return true;
+ }
+
+ void CleanupDeviceD3D()
+ {
+ CleanupRenderTarget();
+ if (mSwapChain) {
+ mSwapChain->Release();
+ mSwapChain = nullptr;
+ }
+ if (mD3dDeviceContext) {
+ mD3dDeviceContext->Release();
+ mD3dDeviceContext = nullptr;
+ }
+ if (mD3dDevice) {
+ mD3dDevice->Release();
+ mD3dDevice = nullptr;
+ }
+ }
+
+ void CreateRenderTarget()
+ {
+ ID3D11Texture2D* pBackBuffer;
+ mSwapChain->GetBuffer(0, IID_PPV_ARGS(&pBackBuffer));
+ mD3dDevice->CreateRenderTargetView(pBackBuffer, nullptr, &mMainRenderTargetView);
+ pBackBuffer->Release();
+ }
+
+ void CleanupRenderTarget()
+ {
+ if (mMainRenderTargetView) {
+ mMainRenderTargetView->Release();
+ mMainRenderTargetView = nullptr;
+ }
+ }
+
+ static LRESULT CALLBACK StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
+ {
+ DirectX11Backend* self;
+ if (uMsg == WM_NCCREATE) {
+ auto lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
+ self = static_cast<DirectX11Backend*>(lpcs->lpCreateParams);
+ self->hWnd = hWnd;
+ SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(self));
+ } else {
+ self = reinterpret_cast<DirectX11Backend*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
+ }
+
+ if (self) {
+ return self->WndProc(uMsg, wParam, lParam);
+ } else {
+ return DefWindowProc(hWnd, uMsg, wParam, lParam);
+ }
+ }
+
+ LRESULT WndProc(UINT msg, WPARAM wParam, LPARAM lParam)
+ {
+ if (ImGui_ImplWin32_WndProcHandler(hWnd, msg, wParam, lParam)) {
+ return true;
+ }
+
+ switch (msg) {
+ case WM_SIZE: {
+ if (mD3dDevice != nullptr && wParam != SIZE_MINIMIZED) {
+ CleanupRenderTarget();
+ mSwapChain->ResizeBuffers(0, (UINT)LOWORD(lParam), (UINT)HIWORD(lParam), DXGI_FORMAT_UNKNOWN, 0);
+ CreateRenderTarget();
+ }
+ return 0;
+ }
+
+ case WM_SYSCOMMAND: {
+ // Disable ALT application menu
+ if ((wParam & 0xfff0) == SC_KEYMENU) {
+ return 0;
+ }
+ } break;
+
+ case WM_DESTROY: {
+ ::PostQuitMessage(0);
+ return 0;
+ }
+ }
+ return ::DefWindowProc(hWnd, msg, wParam, lParam);
+ }
+};
+
+std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend()
+{
+ try {
+ return std::make_unique<DirectX11Backend>();
+ } catch (std::exception& e) {
+ return nullptr;
+ }
+}
+
+#else // ^^ BUILD_CORE_WITH_DX11_BACKEND | BUILD_CORE_WITH_DX11_BACKEND vv
+
+std::unique_ptr<RenderingBackend> RenderingBackend::CreateDx11Backend()
+{
+ return nullptr;
+}
+
+#endif