diff options
author | rtk0c <[email protected]> | 2021-04-10 21:13:34 -0700 |
---|---|---|
committer | rtk0c <[email protected]> | 2021-04-10 21:13:34 -0700 |
commit | 568fcc1dfe40c37b57b7baa2dea93b291d3fa956 (patch) | |
tree | 826b410c502a950c1d4804d351959da914003b36 /core/src/Entrypoint/Backend_DirectX11.cpp | |
parent | 4303d0be47526b35e5bb3e3be001da227dae5d96 (diff) |
Add dx11, dx12, and vulkan backends
Diffstat (limited to 'core/src/Entrypoint/Backend_DirectX11.cpp')
-rw-r--r-- | core/src/Entrypoint/Backend_DirectX11.cpp | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/core/src/Entrypoint/Backend_DirectX11.cpp b/core/src/Entrypoint/Backend_DirectX11.cpp new file mode 100644 index 0000000..8d46bf4 --- /dev/null +++ b/core/src/Entrypoint/Backend_DirectX11.cpp @@ -0,0 +1,238 @@ +#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 |