Skip to content

Commit

Permalink
Fix/implement DPI scaling
Browse files Browse the repository at this point in the history
- DPI scaling:
  - Added DPI scaling manifest
  - implement DPI change event handler
  - use imgui fork for proper font atlas reloading: ocornut/imgui#3761
  - implement UI element and font scaling on DPI change
  - reset UI widths on DPI change
- Prevent crash when VDFs/level can not be found
- Properly clean up D3D objects on exit
  • Loading branch information
Katharsas committed Nov 12, 2024
1 parent 065f833 commit 5509fb0
Show file tree
Hide file tree
Showing 40 changed files with 7,875 additions and 2,764 deletions.
4 changes: 2 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ if (BUILD_MODE STREQUAL Debug)
elseif (BUILD_MODE STREQUAL Release)
message(STATUS "BuildMode: Release" )
else()
message(FATAL_ERROR "Only 'Debug' or 'Release' build type supported!")
message(FATAL_ERROR "Only 'Debug' or 'Release' build type supported! Make sure to pass -DCMAKE_CONFIGURATION_TYPES=<type>")
endif()

####### General options
Expand Down Expand Up @@ -99,7 +99,7 @@ message(STATUS "############## EXECUTABLE ##############")

link_directories(${DXSDK_LIB_DIR})

file(GLOB_RECURSE PROJECT_SRC CONFIGURE_DEPENDS "src/*.h" "src/*.cpp" "src/*.rc")
file(GLOB_RECURSE PROJECT_SRC CONFIGURE_DEPENDS "src/*.h" "src/*.cpp" "src/*.rc" "src/app.manifest")
add_executable(${PROJECT_NAME} WIN32 ${PROJECT_SRC})

if (MSVC)
Expand Down
13 changes: 9 additions & 4 deletions lib/imgui/imconfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,11 @@

//---- Define attributes of all API symbols declarations, e.g. for DLL under Windows
// Using Dear ImGui via a shared library is not recommended, because of function call overhead and because we don't guarantee backward nor forward ABI compatibility.
// DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec( dllexport )
//#define IMGUI_API __declspec( dllimport )
// - Windows DLL users: heaps and globals are not shared across DLL boundaries! You will need to call SetCurrentContext() + SetAllocatorFunctions()
// for each static/DLL boundary you are calling from. Read "Context and Memory Allocators" section of imgui.cpp for more details.
//#define IMGUI_API __declspec(dllexport) // MSVC Windows: DLL export
//#define IMGUI_API __declspec(dllimport) // MSVC Windows: DLL import
//#define IMGUI_API __attribute__((visibility("default"))) // GCC/Clang: override visibility when set is hidden

//---- Don't define obsolete functions/enums/behaviors. Consider enabling from time to time after updating to clean your code of obsolete function/names.
//#define IMGUI_DISABLE_OBSOLETE_FUNCTIONS
Expand All @@ -42,13 +43,17 @@
//#define IMGUI_DISABLE_WIN32_DEFAULT_IME_FUNCTIONS // [Win32] [Default with non-Visual Studio compilers] Don't implement default IME handler (won't require imm32.lib/.a)
//#define IMGUI_DISABLE_WIN32_FUNCTIONS // [Win32] Won't use and link with any Win32 function (clipboard, IME).
//#define IMGUI_ENABLE_OSX_DEFAULT_CLIPBOARD_FUNCTIONS // [OSX] Implement default OSX clipboard handler (need to link with '-framework ApplicationServices', this is why this is not the default).
//#define IMGUI_DISABLE_DEFAULT_SHELL_FUNCTIONS // Don't implement default platform_io.Platform_OpenInShellFn() handler (Win32: ShellExecute(), require shell32.lib/.a, Mac/Linux: use system("")).
//#define IMGUI_DISABLE_DEFAULT_FORMAT_FUNCTIONS // Don't implement ImFormatString/ImFormatStringV so you can implement them yourself (e.g. if you don't want to link with vsnprintf)
//#define IMGUI_DISABLE_DEFAULT_MATH_FUNCTIONS // Don't implement ImFabs/ImSqrt/ImPow/ImFmod/ImCos/ImSin/ImAcos/ImAtan2 so you can implement them yourself.
//#define IMGUI_DISABLE_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle at all (replace them with dummies)
//#define IMGUI_DISABLE_DEFAULT_FILE_FUNCTIONS // Don't implement ImFileOpen/ImFileClose/ImFileRead/ImFileWrite and ImFileHandle so you can implement them yourself if you don't want to link with fopen/fclose/fread/fwrite. This will also disable the LogToTTY() function.
//#define IMGUI_DISABLE_DEFAULT_ALLOCATORS // Don't implement default allocators calling malloc()/free() to avoid linking with them. You will need to call ImGui::SetAllocatorFunctions().
//#define IMGUI_DISABLE_SSE // Disable use of SSE intrinsics even if available

//---- Enable Test Engine / Automation features.
//#define IMGUI_ENABLE_TEST_ENGINE // Enable imgui_test_engine hooks. Generally set automatically by include "imgui_te_config.h", see Test Engine for details.

//---- Include imgui_user.h at the end of imgui.h as a convenience
// May be convenient for some users to only explicitly include vanilla imgui.h and have extra stuff included.
//#define IMGUI_INCLUDE_IMGUI_USER_H
Expand Down
2,378 changes: 1,680 additions & 698 deletions lib/imgui/imgui.cpp

Large diffs are not rendered by default.

889 changes: 692 additions & 197 deletions lib/imgui/imgui.h

Large diffs are not rendered by default.

2,789 changes: 2,348 additions & 441 deletions lib/imgui/imgui_demo.cpp

Large diffs are not rendered by default.

425 changes: 308 additions & 117 deletions lib/imgui/imgui_draw.cpp

Large diffs are not rendered by default.

113 changes: 72 additions & 41 deletions lib/imgui/imgui_impl_dx11.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
// TODO ON UPDATE!
// Disable pragma warning C4005, see #pragma warning(..) around <d3d11.h>

// dear imgui: Renderer Backend for DirectX11
// This needs to be used along with a Platform Backend (e.g. Win32)

Expand All @@ -18,6 +15,7 @@

// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2023-XX-XX: DirectX11: Add support for ImGuiBackendFlags_RendererHasTexReload.
// 2022-10-11: Using 'nullptr' instead of 'NULL' as per our switch to C++11.
// 2021-06-29: Reorganized backend to pull data from a single structure to facilitate usage with multiple-contexts (all g_XXXX access changed to bd->XXXX).
// 2021-05-19: DirectX11: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement)
Expand All @@ -42,12 +40,7 @@

// DirectX
#include <stdio.h>

#pragma warning(push)
#pragma warning(disable : 4005)
#include <d3d11.h>
#pragma warning(pop)

#include <d3dcompiler.h>
#ifdef _MSC_VER
#pragma comment(lib, "d3dcompiler") // Automatically link with d3dcompiler.lib as we are using D3DCompile() below.
Expand All @@ -66,6 +59,9 @@ struct ImGui_ImplDX11_Data
ID3D11Buffer* pVertexConstantBuffer;
ID3D11PixelShader* pPixelShader;
ID3D11SamplerState* pFontSampler;
ID3D11Texture2D* pFontTexture;
int FontTextureWidth;
int FontTextureHeight;
ID3D11ShaderResourceView* pFontTextureView;
ID3D11RasterizerState* pRasterizerState;
ID3D11BlendState* pBlendState;
Expand Down Expand Up @@ -316,53 +312,81 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data)
ctx->IASetInputLayout(old.InputLayout); if (old.InputLayout) old.InputLayout->Release();
}

static void ImGui_ImplDX11_CreateFontsTexture()
static void ImGui_ImplDX11_UpdateFontsTexture()
{
// Build texture atlas
ImGuiIO& io = ImGui::GetIO();
ImGui_ImplDX11_Data* bd = ImGui_ImplDX11_GetBackendData();

// Build texture atlas
unsigned char* pixels;
int width, height;
io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);
io.Fonts->MarkClean();

// Upload texture to graphics system
if ((!bd->pFontTextureView) || (bd->FontTextureWidth != width) || (bd->FontTextureHeight != height))
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;

ID3D11Texture2D* pTexture = nullptr;
D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &pTexture);
IM_ASSERT(pTexture != nullptr);

// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(pTexture, &srvDesc, &bd->pFontTextureView);
pTexture->Release();
// Either we have no texture or the size has changed, so (re-)create the texture

// Release old texture
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied g_pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pFontTexture) { bd->pFontTexture->Release(); bd->pFontTexture = nullptr; }

// Create new texture
{
D3D11_TEXTURE2D_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;

D3D11_SUBRESOURCE_DATA subResource;
subResource.pSysMem = pixels;
subResource.SysMemPitch = desc.Width * 4;
subResource.SysMemSlicePitch = 0;
bd->pd3dDevice->CreateTexture2D(&desc, &subResource, &bd->pFontTexture);
IM_ASSERT(bd->pFontTexture != nullptr);

// Create texture view
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc;
ZeroMemory(&srvDesc, sizeof(srvDesc));
srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
srvDesc.Texture2D.MipLevels = desc.MipLevels;
srvDesc.Texture2D.MostDetailedMip = 0;
bd->pd3dDevice->CreateShaderResourceView(bd->pFontTexture, &srvDesc, &bd->pFontTextureView);
}

// Store size
bd->FontTextureWidth = width;
bd->FontTextureHeight = height;
}
else
{
// Upload new atlas data

D3D11_BOX box;
box.left = 0;
box.right = width;
box.top = 0;
box.bottom = height;
box.front = 0;
box.back = 1;

bd->pd3dDeviceContext->UpdateSubresource(bd->pFontTexture, 0, &box, pixels, bd->FontTextureWidth * 4, 0);
}

// Store our identifier
io.Fonts->SetTexID((ImTextureID)bd->pFontTextureView);

// Create texture sampler
// (Bilinear sampling is required by default. Set 'io.Fonts->Flags |= ImFontAtlasFlags_NoBakedLines' or 'style.AntiAliasedLinesUseTex = false' to allow point/nearest sampling)
if (!bd->pFontSampler)
{
D3D11_SAMPLER_DESC desc;
ZeroMemory(&desc, sizeof(desc));
Expand Down Expand Up @@ -527,7 +551,7 @@ bool ImGui_ImplDX11_CreateDeviceObjects()
bd->pd3dDevice->CreateDepthStencilState(&desc, &bd->pDepthStencilState);
}

ImGui_ImplDX11_CreateFontsTexture();
ImGui_ImplDX11_UpdateFontsTexture();

return true;
}
Expand All @@ -540,6 +564,7 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()

if (bd->pFontSampler) { bd->pFontSampler->Release(); bd->pFontSampler = nullptr; }
if (bd->pFontTextureView) { bd->pFontTextureView->Release(); bd->pFontTextureView = nullptr; ImGui::GetIO().Fonts->SetTexID(0); } // We copied data->pFontTextureView to io.Fonts->TexID so let's clear that as well.
if (bd->pFontTexture) { bd->pFontTexture->Release(); bd->pFontTexture = nullptr; }
if (bd->pIB) { bd->pIB->Release(); bd->pIB = nullptr; }
if (bd->pVB) { bd->pVB->Release(); bd->pVB = nullptr; }
if (bd->pBlendState) { bd->pBlendState->Release(); bd->pBlendState = nullptr; }
Expand All @@ -554,13 +579,15 @@ void ImGui_ImplDX11_InvalidateDeviceObjects()
bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context)
{
ImGuiIO& io = ImGui::GetIO();
IMGUI_CHECKVERSION();
IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!");

// Setup backend capabilities flags
ImGui_ImplDX11_Data* bd = IM_NEW(ImGui_ImplDX11_Data)();
io.BackendRendererUserData = (void*)bd;
io.BackendRendererName = "imgui_impl_dx11";
io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes.
io.BackendFlags |= ImGuiBackendFlags_RendererHasTexReload; // We support font atlas texture reloading (IsDirty() check in ImGui_ImplDX11_NewFrame)

// Get factory from device
IDXGIDevice* pDXGIDevice = nullptr;
Expand Down Expand Up @@ -606,6 +633,10 @@ void ImGui_ImplDX11_NewFrame()

if (!bd->pFontSampler)
ImGui_ImplDX11_CreateDeviceObjects();

ImGuiIO& io = ImGui::GetIO();
if (io.Fonts->IsDirty())
ImGui_ImplDX11_UpdateFontsTexture();
}

//-----------------------------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions lib/imgui/imgui_impl_dx11.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
struct ID3D11Device;
struct ID3D11DeviceContext;

// Follow "Getting Started" link and check examples/ folder to learn about using backends!
IMGUI_IMPL_API bool ImGui_ImplDX11_Init(ID3D11Device* device, ID3D11DeviceContext* device_context);
IMGUI_IMPL_API void ImGui_ImplDX11_Shutdown();
IMGUI_IMPL_API void ImGui_ImplDX11_NewFrame();
Expand Down
Loading

0 comments on commit 5509fb0

Please sign in to comment.