Merge branch 'master' into docking

# Conflicts:
#	backends/imgui_impl_dx12.cpp
#	docs/CHANGELOG.txt
#	imgui.cpp
This commit is contained in:
ocornut
2025-10-13 15:13:06 +02:00
14 changed files with 233 additions and 170 deletions

View File

@@ -42,5 +42,5 @@ jobs:
fi
cd examples/example_null
pvs-studio-analyzer trace -- make WITH_EXTRA_WARNINGS=1
pvs-studio-analyzer analyze --disableLicenseExpirationCheck -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
pvs-studio-analyzer analyze -e ../../imstb_rectpack.h -e ../../imstb_textedit.h -e ../../imstb_truetype.h -l ../../pvs-studio.lic -o pvs-studio.log
plog-converter -a 'GA:1,2;OP:1' -d V1071 -t errorfile -w pvs-studio.log

View File

@@ -23,6 +23,7 @@
// CHANGELOG
// (minor and older changes stripped away, please see git history for details)
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
// 2025-10-11: DirectX12: Reuse texture upload buffer and grow it only when necessary. (#9002)
// 2025-09-29: DirectX12: Rework synchronization logic. (#8961)
// 2025-09-29: DirectX12: Enable swapchain tearing to eliminate viewports framerate throttling. (#8965)
// 2025-09-29: DirectX12: Reuse a command list and allocator for texture uploads instead of recreating them each time. (#8963)
@@ -111,6 +112,9 @@ struct ImGui_ImplDX12_Data
ID3D12CommandAllocator* pTexCmdAllocator;
ID3D12GraphicsCommandList* pTexCmdList;
ID3D12Resource* pTexUploadBuffer;
UINT pTexUploadBufferSize;
void* pTexUploadBufferMapped;
ImGui_ImplDX12_Data() { memset((void*)this, 0, sizeof(*this)); }
};
@@ -513,6 +517,16 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
UINT upload_pitch_dst = (upload_pitch_src + D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u) & ~(D3D12_TEXTURE_DATA_PITCH_ALIGNMENT - 1u);
UINT upload_size = upload_pitch_dst * upload_h;
if (bd->pTexUploadBuffer == nullptr || upload_size > bd->pTexUploadBufferSize)
{
if (bd->pTexUploadBufferMapped)
{
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
bd->pTexUploadBuffer->Unmap(0, &range);
bd->pTexUploadBufferMapped = nullptr;
}
SafeRelease(bd->pTexUploadBuffer);
D3D12_RESOURCE_DESC desc;
ZeroMemory(&desc, sizeof(desc));
desc.Dimension = D3D12_RESOURCE_DIMENSION_BUFFER;
@@ -533,24 +547,23 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
props.CPUPageProperty = D3D12_CPU_PAGE_PROPERTY_UNKNOWN;
props.MemoryPoolPreference = D3D12_MEMORY_POOL_UNKNOWN;
// FIXME-OPT: Could upload buffer be kept around, reused, and grown only when needed? Would that be worth it?
ID3D12Resource* uploadBuffer = nullptr;
HRESULT hr = bd->pd3dDevice->CreateCommittedResource(&props, D3D12_HEAP_FLAG_NONE, &desc,
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&uploadBuffer));
D3D12_RESOURCE_STATE_GENERIC_READ, nullptr, IID_PPV_ARGS(&bd->pTexUploadBuffer));
IM_ASSERT(SUCCEEDED(hr));
D3D12_RANGE range = {0, upload_size};
hr = bd->pTexUploadBuffer->Map(0, &range, &bd->pTexUploadBufferMapped);
IM_ASSERT(SUCCEEDED(hr));
bd->pTexUploadBufferSize = upload_size;
}
bd->pTexCmdAllocator->Reset();
bd->pTexCmdList->Reset(bd->pTexCmdAllocator, nullptr);
ID3D12GraphicsCommandList* cmdList = bd->pTexCmdList;
// Copy to upload buffer
void* mapped = nullptr;
D3D12_RANGE range = { 0, upload_size };
hr = uploadBuffer->Map(0, &range, &mapped);
IM_ASSERT(SUCCEEDED(hr));
for (int y = 0; y < upload_h; y++)
memcpy((void*)((uintptr_t)mapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
uploadBuffer->Unmap(0, &range);
memcpy((void*)((uintptr_t)bd->pTexUploadBufferMapped + y * upload_pitch_dst), tex->GetPixelsAt(upload_x, upload_y + y), upload_pitch_src);
if (need_barrier_before_copy)
{
@@ -567,7 +580,7 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
D3D12_TEXTURE_COPY_LOCATION srcLocation = {};
D3D12_TEXTURE_COPY_LOCATION dstLocation = {};
{
srcLocation.pResource = uploadBuffer;
srcLocation.pResource = bd->pTexUploadBuffer;
srcLocation.Type = D3D12_TEXTURE_COPY_TYPE_PLACED_FOOTPRINT;
srcLocation.PlacedFootprint.Footprint.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srcLocation.PlacedFootprint.Footprint.Width = upload_w;
@@ -591,9 +604,8 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
cmdList->ResourceBarrier(1, &barrier);
}
hr = cmdList->Close();
HRESULT hr = cmdList->Close();
IM_ASSERT(SUCCEEDED(hr));
ID3D12CommandQueue* cmdQueue = bd->pCommandQueue;
cmdQueue->ExecuteCommandLists(1, (ID3D12CommandList* const*)&cmdList);
hr = cmdQueue->Signal(bd->Fence, ++bd->FenceLastSignaledValue);
@@ -606,7 +618,6 @@ void ImGui_ImplDX12_UpdateTexture(ImTextureData* tex)
bd->Fence->SetEventOnCompletion(bd->FenceLastSignaledValue, bd->FenceEvent);
::WaitForSingleObject(bd->FenceEvent, INFINITE);
uploadBuffer->Release();
tex->SetStatus(ImTextureStatus_OK);
}
@@ -886,6 +897,13 @@ void ImGui_ImplDX12_InvalidateDeviceObjects()
bd->commandQueueOwned = false;
SafeRelease(bd->pRootSignature);
SafeRelease(bd->pPipelineState);
if (bd->pTexUploadBufferMapped)
{
D3D12_RANGE range = { 0, bd->pTexUploadBufferSize };
bd->pTexUploadBuffer->Unmap(0, &range);
bd->pTexUploadBufferMapped = nullptr;
}
SafeRelease(bd->pTexUploadBuffer);
SafeRelease(bd->pTexCmdList);
SafeRelease(bd->pTexCmdAllocator);
SafeRelease(bd->Fence);

View File

@@ -48,7 +48,7 @@
#include "imgui.h"
// When targeting native platforms (i.e. NOT emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// When targeting native platforms (i.e. NOT Emscripten), one of IMGUI_IMPL_WEBGPU_BACKEND_DAWN
// or IMGUI_IMPL_WEBGPU_BACKEND_WGPU must be provided. See imgui_impl_wgpu.h for more details.
#ifndef __EMSCRIPTEN__
#if defined(IMGUI_IMPL_WEBGPU_BACKEND_DAWN) == defined(IMGUI_IMPL_WEBGPU_BACKEND_WGPU)

View File

@@ -34,7 +34,7 @@
// Initialization data, for ImGui_ImplWGPU_Init()
struct ImGui_ImplWGPU_InitInfo
{
WGPUDevice Device;
WGPUDevice Device = nullptr;
int NumFramesInFlight = 3;
WGPUTextureFormat RenderTargetFormat = WGPUTextureFormat_Undefined;
WGPUTextureFormat DepthStencilFormat = WGPUTextureFormat_Undefined;

View File

@@ -45,78 +45,97 @@ Breaking Changes:
io.ConfigViewportPlatformFocusSetsImGuiFocus
to io.ConfigViewportsPlatformFocusSetsImGuiFocus. (#6299, #6462)
It was really a typo in the first place, and introduced in 1.92.2.
- Backends: Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
- Backends:
- Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo:
init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass
init_info.Subpass --> init_info.PipelineInfoMain.Subpass
init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples
init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo
It makes things more consistent and was desirable to introduce new settings for
secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz]
- Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
- Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo
(introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()`
so it should not affect many users). (#8110, #8111)
- Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
`VkImageUsageFlags image_usage` argument to specific extra flags for calls to
vkCreateSwapchainKHR() done for secondary viewports. We automatically add
`VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT`. In theory the function is an internal
helper but since it's used by our examples some may have used it. (#8946, #8111, #8686)
- Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a
`VkImageUsageFlags image_usage` argument.
It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults
to that when the value is 0. In theory the function is an internal helper but
since it's used by our examples some may have used it. (#8946, #8111, #8686)
Other Changes:
- Windows: added lower-right resize grip on child windows using both
ImGuiChildFlags_ResizeX and ImGuiChildFlags_ResizeY flags. (#8501) [@aleksijuvani]
The grip is not visible before hovering to reduce clutter.
- InputText: fixed single-line InputText() not applying fine character clipping
properly (regression in 1.92.3). (#8967) [@Cyphall]
- Style: added ImGuiCol_UnsavedMarker, color of the unsaved document marker when
using ImGuiWindowFlags_UnsavedDocument/ImGuiTabItemFlags_UnsavedDocument. (#8983)
- IO: added ImGuiPlatformIO::ClearPlatformHandlers(), ClearRendererHandlers()
helpers to null all handlers. (#8945, #2769)
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
See misc/debuggers/ for details. (#8950) [@mentlerd]
- Textures: fixed a crash if texture status is set to _WantDestroy by a backend after
- Inputs:
- Shortcuts: added support for combining ImGuiInputFlags_RouteFocused
(which is the default route) with ImGuiInputFlags_RouteOverActive, allowing
to steal shortcuts from active item without using global routing. (#9004)
- InputText:
- Fixed single-line InputText() not applying fine character clipping
properly (regression in 1.92.3). (#8967) [@Cyphall]
- Fixed an infinite loop error happening if a custom input text
callback modifies/clear BufTextLen before calling InsertChars().
(regression from 1.92.3). Note that this never really worked correctly, but
previously it would only temporary wreck cursor position, and since 1.92.3 it
would go in an infinite loop. (#8994, #3237)
- Textures:
- Fixed a crash if texture status is set to _WantDestroy by a backend after
it had already been destroyed. This would typically happen when calling backend's
ImGui_ImplXXXX_InvalidateDeviceObjects() helpers twice in a row. (#8977, #8811)
- Textures: allowed backend to destroy texture while inside the NewFrame/EndFrame
- Allowed backend to destroy texture while inside the NewFrame/EndFrame
scope. Basically if a backend decide to destroy a texture that we didn't request
to destroy (for e.g. freeing resources) the texture is immediately set to
a _WantCreate status again. (#8811)
- Textures: fixed an issue preventing multi-contexts sharing a ImFontAtlas from
- Fixed an issue preventing multi-contexts sharing a ImFontAtlas from
being possible to destroy in any order.
- Textures: fixed not updating ImTextureData's RefCount when destroying a context
using a shared ImFontAtlas, leading standard backends to not properly free
texture resources. (#8975) [@icrashstuff]
- CI: Updates Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
- Backends: all backends call ImGuiPlatformIO::ClearPlatformHandlers() and
ClearRendererHandlers() on shutdown, so as not to leave function pointers
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
- Fixed not updating ImTextureData's RefCount when destroying a context
using a shared ImFontAtlas, leading standard backends to not properly
free texture resources. (#8975) [@icrashstuff]
- Demo: fixed layout issue in "Layout & Scrolling -> Scrolling" section.
- Misc: Debuggers: added type formatters for the LLDB debuggers (e.g. Xcode,
Android Studio & more) to provide nicer display for ImVec2, ImVec4, ImVector etc.
See misc/debuggers/ for details. (#8950) [@mentlerd]
- CI: updated Windows CI scripts to generate/use VulkanSDK. (#8925, #8778) [@yaz0r]
- Docs: updated FAQ with new "What is the difference between Dear ImGui and
traditional UI toolkits?" entry. (#8862)
- Backends: DirectX12: reuse a command list and allocator for texture uploads instead
- Backends:
- All backends call ImGuiPlatformIO::ClearPlatformHandlers() and
ClearRendererHandlers() on shutdown, so as not to leave function pointers
which may be dangling when using backend in e.g. DLL. (#8945, #2769)
- DirectX12: reuse a command list and allocator for texture uploads instead
of recreating them each time. (#8963, #8465) [@RT2Code]
- Backends: DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
- DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
(presumably fixes old hard-to-repro crash issues such as #3463, #5018)
- Backends: DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
- Backends: OpenGL3: fixed GL loader to work on Haiku OS which does not support
- DirectX12: Reuse texture upload buffer and grow it only when
necessary. (#9002) [@RT2Code]
- DirectX12: Enable swapchain tearing if available. (#8965) [@RT2Code]
- OpenGL3: fixed GL loader to work on Haiku OS which does not support
`RTLD_NOLOAD`. (#8952) [@Xottab-DUTY, @threedeyes]
- Backends: GLFW: fixed build on platform that are neither Windows, macOS or
- GLFW: fixed build on platform that are neither Windows, macOS or
known Unixes (Regression in 1.92.3). (#8969, #8920, #8921) [@oktonion]
- Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
- SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our
window is hovered, as the event data is reliable and enough in this case.
- Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786)
- Essentially a working for SDL3 bug which will be fixed in SDL 3.3.0.
- Essentially a workaround for SDL3 bug which will be fixed in SDL 3.3.0.
- Better perf on X11 as querying global position requires a round trip to X11 server.
- Backends: Win32: minor optimization not submitting gamepad io again if
- Win32: minor optimization not submitting gamepad io again if
XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN]
- Backends: Vulkan: added a way to specify custom shaders by filling init fields
- Vulkan: added a way to specify custom shaders by filling init fields
CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A]
- Backends: DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
- DX9,DX10,DX11,DX12,Metal,Vulkan,WGPU,SDLRenderer2,SDLRenderer3:
ensure that a texture in _WantDestroy state always turn to _Destroyed even
if your underlying graphics data was already destroyed. (#8977)
- Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is
- Examples:
- SDL2+DirectX11: Try WARP software driver if hardware driver is
not available. (#5924, #5562)
- Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
- Examples: Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
- Examples: made examples's main.cpp consistent with returning 1 on error.
- SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82]
- Win32+DirectX12: Rework synchronization logic. (#8961) [@RT2Code]
- Made examples's main.cpp consistent with returning 1 on error.
Docking+Viewports Branch:

View File

@@ -1,4 +1,4 @@
// Dear ImGui: standalone example application for using GLFW + WebGPU
// Dear ImGui: standalone example application for GLFW + WebGPU
// - Emscripten is supported for publishing on web. See https://emscripten.org.
// - Dawn is used as a WebGPU implementation on desktop.
@@ -12,36 +12,32 @@
#include "imgui_impl_glfw.h"
#include "imgui_impl_wgpu.h"
#include <stdio.h>
#include <GLFW/glfw3.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include <emscripten.h>
#include <emscripten/html5.h>
#include <emscripten/html5_webgpu.h>
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#else
#include <webgpu/webgpu_glfw.h>
#endif
#include <GLFW/glfw3.h>
#include <webgpu/webgpu.h>
#include <webgpu/webgpu_cpp.h>
// This example can also compile and run with Emscripten! See 'Makefile.emscripten' for details.
#ifdef __EMSCRIPTEN__
#include "../libs/emscripten/emscripten_mainloop_stub.h"
#endif
// Global WebGPU required states
// Data
static WGPUInstance wgpu_instance = nullptr;
static WGPUDevice wgpu_device = nullptr;
static WGPUSurface wgpu_surface = nullptr;
static WGPUTextureFormat wgpu_preferred_fmt = WGPUTextureFormat_RGBA8Unorm;
static WGPUSwapChain wgpu_swap_chain = nullptr;
static int wgpu_swap_chain_width = 1280;
static int wgpu_swap_chain_height = 800;
static int wgpu_surface_width = 1280;
static int wgpu_surface_height = 800;
// Forward declarations
static bool InitWGPU(GLFWwindow* window);
static void CreateSwapChain(int width, int height);
static void ResizeSurface(int width, int height);
static void glfw_error_callback(int error, const char* description)
{
@@ -72,19 +68,23 @@ int main(int, char**)
// Make sure GLFW does not initialize any graphics context.
// This needs to be done explicitly later.
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
GLFWwindow* window = glfwCreateWindow(wgpu_swap_chain_width, wgpu_swap_chain_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
// Create window
float main_scale = ImGui_ImplGlfw_GetContentScaleForMonitor(glfwGetPrimaryMonitor()); // Valid on GLFW 3.3+ only
wgpu_surface_width *= main_scale;
wgpu_surface_height *= main_scale;
GLFWwindow* window = glfwCreateWindow(wgpu_surface_width, wgpu_surface_height, "Dear ImGui GLFW+WebGPU example", nullptr, nullptr);
if (window == nullptr)
return 1;
// Initialize the WebGPU environment
if (!InitWGPU(window))
{
if (window)
glfwDestroyWindow(window);
glfwTerminate();
return 1;
}
CreateSwapChain(wgpu_swap_chain_width, wgpu_swap_chain_height);
ResizeSurface(wgpu_surface_width, wgpu_surface_height);
glfwShowWindow(window);
// Setup Dear ImGui context
@@ -99,6 +99,11 @@ int main(int, char**)
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// Setup scaling
ImGuiStyle& style = ImGui::GetStyle();
style.ScaleAllSizes(main_scale); // Bake a fixed style scale. (until we have a solution for dynamic style scaling, changing this requires resetting Style + calling this again)
style.FontScaleDpi = main_scale; // Set initial font scale. (using io.ConfigDpiScaleFonts=true makes this unnecessary. We leave both here for documentation purpose)
// Setup Platform/Renderer backends
ImGui_ImplGlfw_InitForOther(window, true);
#ifdef __EMSCRIPTEN__
@@ -118,15 +123,14 @@ int main(int, char**)
// - Use '#define IMGUI_ENABLE_FREETYPE' in your imconfig file to use Freetype for higher quality font rendering.
// - Read 'docs/FONTS.md' for more instructions and details. If you like the default font but want it to scale better, consider using the 'ProggyVector' from the same author!
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
// - Emscripten allows preloading a file or folder to be accessible at runtime. See Makefile for details.
//io.Fonts->AddFontDefault();
// - Our Emscripten build process allows embedding fonts to be accessible at runtime from the "fonts/" folder. See Makefile.emscripten for details.
//style.FontSizeBase = 20.0f;
//io.Fonts->AddFontDefault();
#ifndef IMGUI_DISABLE_FILE_FUNCTIONS
//io.Fonts->AddFontFromFileTTF("fonts/segoeui.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/DroidSans.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Roboto-Medium.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/Cousine-Regular.ttf");
//io.Fonts->AddFontFromFileTTF("fonts/ProggyTiny.ttf");
//ImFont* font = io.Fonts->AddFontFromFileTTF("fonts/ArialUni.ttf");
//IM_ASSERT(font != nullptr);
#endif
@@ -161,10 +165,10 @@ int main(int, char**)
// React to changes in screen size
int width, height;
glfwGetFramebufferSize((GLFWwindow*)window, &width, &height);
if (width != wgpu_swap_chain_width || height != wgpu_swap_chain_height)
if (width != wgpu_surface_width || height != wgpu_surface_height)
{
ImGui_ImplWGPU_InvalidateDeviceObjects();
CreateSwapChain(width, height);
ResizeSurface(width, height);
ImGui_ImplWGPU_CreateDeviceObjects();
}
@@ -239,8 +243,8 @@ int main(int, char**)
WGPUCommandBufferDescriptor cmd_buffer_desc = {};
WGPUCommandBuffer cmd_buffer = wgpuCommandEncoderFinish(encoder, &cmd_buffer_desc);
WGPUQueue queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(queue, 1, &cmd_buffer);
WGPUQueue wgpu_queue = wgpuDeviceGetQueue(wgpu_device);
wgpuQueueSubmit(wgpu_queue, 1, &cmd_buffer);
#ifndef __EMSCRIPTEN__
wgpuSwapChainPresent(wgpu_swap_chain);
@@ -312,10 +316,10 @@ static bool InitWGPU(GLFWwindow* window)
#endif
#ifdef __EMSCRIPTEN__
wgpu::SurfaceDescriptorFromCanvasHTMLSelector html_surface_desc = {};
html_surface_desc.selector = "#canvas";
wgpu::SurfaceDescriptorFromCanvasHTMLSelector canvas_desc = {};
canvas_desc.selector = "#canvas";
wgpu::SurfaceDescriptor surface_desc = {};
surface_desc.nextInChain = &html_surface_desc;
surface_desc.nextInChain = &canvas_desc;
wgpu::Surface surface = instance.CreateSurface(&surface_desc);
wgpu::Adapter adapter = {};
@@ -327,6 +331,7 @@ static bool InitWGPU(GLFWwindow* window)
wgpu_preferred_fmt = WGPUTextureFormat_BGRA8Unorm;
#endif
// Moving Dawn objects into WGPU handles
wgpu_instance = instance.MoveToCHandle();
wgpu_surface = surface.MoveToCHandle();
@@ -335,12 +340,12 @@ static bool InitWGPU(GLFWwindow* window)
return true;
}
static void CreateSwapChain(int width, int height)
static void ResizeSurface(int width, int height)
{
if (wgpu_swap_chain)
wgpuSwapChainRelease(wgpu_swap_chain);
wgpu_swap_chain_width = width;
wgpu_swap_chain_height = height;
wgpu_surface_width = width;
wgpu_surface_height = height;
WGPUSwapChainDescriptor swap_chain_desc = {};
swap_chain_desc.usage = WGPUTextureUsage_RenderAttachment;
swap_chain_desc.format = wgpu_preferred_fmt;

View File

@@ -83,6 +83,7 @@
//---- Use FreeType to build and rasterize the font atlas (instead of stb_truetype which is embedded by default in Dear ImGui)
// Requires FreeType headers to be available in the include path. Requires program to be compiled with 'misc/freetype/imgui_freetype.cpp' (in this repository) + the FreeType library (not provided).
// Note that imgui_freetype.cpp may be used _without_ this define, if you manually call ImFontAtlas::SetFontLoader(). The define is simply a convenience.
// On Windows you may use vcpkg with 'vcpkg install freetype --triplet=x64-windows' + 'vcpkg integrate install'.
//#define IMGUI_ENABLE_FREETYPE

View File

@@ -3767,6 +3767,7 @@ const char* ImGui::GetStyleColorName(ImGuiCol idx)
case ImGuiCol_TextSelectedBg: return "TextSelectedBg";
case ImGuiCol_TreeLines: return "TreeLines";
case ImGuiCol_DragDropTarget: return "DragDropTarget";
case ImGuiCol_UnsavedMarker: return "UnsavedMarker";
case ImGuiCol_NavCursor: return "NavCursor";
case ImGuiCol_NavWindowingHighlight: return "NavWindowingHighlight";
case ImGuiCol_NavWindowingDimBg: return "NavWindowingDimBg";
@@ -7551,7 +7552,7 @@ void ImGui::RenderWindowTitleBarContents(ImGuiWindow* window, const ImRect& titl
marker_pos.y = (layout_r.Min.y + layout_r.Max.y) * 0.5f;
if (marker_pos.x > layout_r.Min.x)
{
RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_Text));
RenderBullet(window->DrawList, marker_pos, GetColorU32(ImGuiCol_UnsavedMarker));
clip_r.Max.x = ImMin(clip_r.Max.x, marker_pos.x - (int)(marker_size_x * 0.5f));
}
}
@@ -7572,7 +7573,7 @@ void ImGui::UpdateWindowParentAndRootLinks(ImGuiWindow* window, ImGuiWindowFlags
}
if (parent_window && (flags & ImGuiWindowFlags_Popup))
window->RootWindowPopupTree = parent_window->RootWindowPopupTree;
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup))) // FIXME: simply use _NoTitleBar ?
if (parent_window && !(flags & ImGuiWindowFlags_Modal) && (flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip))) // FIXME: simply use _NoTitleBar ?
window->RootWindowForTitleBarHighlight = parent_window->RootWindowForTitleBarHighlight;
while (window->RootWindowForNav->ChildFlags & ImGuiChildFlags_NavFlattened)
{
@@ -7717,7 +7718,7 @@ bool ImGui::Begin(const char* name, bool* p_open, ImGuiWindowFlags flags)
// Parent window is latched only on the first call to Begin() of the frame, so further append-calls can be done from a different window stack
ImGuiWindow* parent_window_in_stack = (window->DockIsActive && window->DockNode->HostWindow) ? window->DockNode->HostWindow : g.CurrentWindowStack.empty() ? NULL : g.CurrentWindowStack.back().Window;
ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup)) ? parent_window_in_stack : NULL) : window->ParentWindow;
ImGuiWindow* parent_window = first_begin_of_the_frame ? ((flags & (ImGuiWindowFlags_ChildWindow | ImGuiWindowFlags_Popup | ImGuiWindowFlags_Tooltip)) ? parent_window_in_stack : NULL) : window->ParentWindow;
IM_ASSERT(parent_window != NULL || !(flags & ImGuiWindowFlags_ChildWindow));
// We allow window memory to be compacted so recreate the base stack when needed.
@@ -9997,7 +9998,7 @@ static void ImGui::UpdateKeyRoutingTable(ImGuiKeyRoutingTable* rt)
routing_entry->RoutingCurrScore = routing_entry->RoutingNextScore;
routing_entry->RoutingCurr = routing_entry->RoutingNext; // Update entry
routing_entry->RoutingNext = ImGuiKeyOwner_NoOwner;
routing_entry->RoutingNextScore = 255;
routing_entry->RoutingNextScore = 0;
if (routing_entry->RoutingCurr == ImGuiKeyOwner_NoOwner)
continue;
rt->EntriesNext.push_back(*routing_entry); // Write alive ones into new buffer
@@ -10066,23 +10067,24 @@ ImGuiKeyRoutingData* ImGui::GetShortcutRoutingData(ImGuiKeyChord key_chord)
return routing_data;
}
// Current score encoding (lower is highest priority):
// - 0: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive
// - 1: ImGuiInputFlags_ActiveItem or ImGuiInputFlags_RouteFocused (if item active)
// - 2: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused
// - 3+: ImGuiInputFlags_RouteFocused (if window in focus-stack)
// - 254: ImGuiInputFlags_RouteGlobal
// - 255: never route
// Current score encoding
// - 0: Never route
// - 1: ImGuiInputFlags_RouteGlobal (lower priority)
// - 100..199: ImGuiInputFlags_RouteFocused (if window in focus-stack)
// 200: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverFocused
// 300: ImGuiInputFlags_RouteActive or ImGuiInputFlags_RouteFocused (if item active)
// 400: ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteOverActive
// - 500..599: ImGuiInputFlags_RouteFocused | ImGuiInputFlags_RouteOverActive (if window in focus-stack) (higher priority)
// 'flags' should include an explicit routing policy
static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInputFlags flags)
{
ImGuiContext& g = *GImGui;
if (flags & ImGuiInputFlags_RouteFocused)
{
// ActiveID gets top priority
// ActiveID gets high priority
// (we don't check g.ActiveIdUsingAllKeys here. Routing is applied but if input ownership is tested later it may discard it)
if (owner_id != 0 && g.ActiveId == owner_id)
return 1;
return 300;
// Score based on distance to focused window (lower is better)
// Assuming both windows are submitting a routing request,
@@ -10092,25 +10094,32 @@ static int CalcRoutingScore(ImGuiID focus_scope_id, ImGuiID owner_id, ImGuiInput
// - When Window/ChildB is focused -> Window scores 4 (best), Window/ChildB doesn't have a score.
// This essentially follow the window->ParentWindowForFocusRoute chain.
if (focus_scope_id == 0)
return 255;
return 0;
for (int index_in_focus_path = 0; index_in_focus_path < g.NavFocusRoute.Size; index_in_focus_path++)
if (g.NavFocusRoute.Data[index_in_focus_path].ID == focus_scope_id)
return 3 + index_in_focus_path;
return 255;
{
if (flags & ImGuiInputFlags_RouteOverActive) // && g.ActiveId != 0 && g.ActiveId != owner_id)
return 599 - index_in_focus_path;
else
return 199 - index_in_focus_path;
}
return 0;
}
else if (flags & ImGuiInputFlags_RouteActive)
{
if (owner_id != 0 && g.ActiveId == owner_id)
return 1;
return 255;
return 300;
return 0;
}
else if (flags & ImGuiInputFlags_RouteGlobal)
{
if (flags & ImGuiInputFlags_RouteOverActive)
return 0;
return 400;
if (owner_id != 0 && g.ActiveId == owner_id)
return 300;
if (flags & ImGuiInputFlags_RouteOverFocused)
return 2;
return 254;
return 200;
return 1;
}
IM_ASSERT(0);
return 0;
@@ -10150,8 +10159,10 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I
else
IM_ASSERT(ImIsPowerOfTwo(flags & ImGuiInputFlags_RouteTypeMask_)); // Check that only 1 routing flag is used
IM_ASSERT(owner_id != ImGuiKeyOwner_Any && owner_id != ImGuiKeyOwner_NoOwner);
if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteOverActive | ImGuiInputFlags_RouteUnlessBgFocused))
if (flags & (ImGuiInputFlags_RouteOverFocused | ImGuiInputFlags_RouteUnlessBgFocused))
IM_ASSERT(flags & ImGuiInputFlags_RouteGlobal);
if (flags & ImGuiInputFlags_RouteOverActive)
IM_ASSERT(flags & (ImGuiInputFlags_RouteGlobal | ImGuiInputFlags_RouteFocused));
// Add ImGuiMod_XXXX when a corresponding ImGuiKey_LeftXXX/ImGuiKey_RightXXX is specified.
key_chord = FixupKeyChord(key_chord);
@@ -10206,17 +10217,17 @@ bool ImGui::SetShortcutRouting(ImGuiKeyChord key_chord, ImGuiInputFlags flags, I
const int score = CalcRoutingScore(focus_scope_id, owner_id, flags);
IMGUI_DEBUG_LOG_INPUTROUTING("SetShortcutRouting(%s, flags=%04X, owner_id=0x%08X) -> score %d\n", GetKeyChordName(key_chord), flags, owner_id, score);
if (score == 255)
if (score == 0)
return false;
// Submit routing for NEXT frame (assuming score is sufficient)
// FIXME: Could expose a way to use a "serve last" policy for same score resolution (using <= instead of <).
// FIXME: Could expose a way to use a "serve last" policy for same score resolution (using >= instead of >).
ImGuiKeyRoutingData* routing_data = GetShortcutRoutingData(key_chord);
//const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score <= routing_data->RoutingNextScore) : (score < routing_data->RoutingNextScore);
if (score < routing_data->RoutingNextScore)
//const bool set_route = (flags & ImGuiInputFlags_ServeLast) ? (score >= routing_data->RoutingNextScore) : (score > routing_data->RoutingNextScore);
if (score > routing_data->RoutingNextScore)
{
routing_data->RoutingNext = owner_id;
routing_data->RoutingNextScore = (ImU8)score;
routing_data->RoutingNextScore = (ImU16)score;
}
// Return routing state for CURRENT frame

View File

@@ -29,7 +29,7 @@
// Library Version
// (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345')
#define IMGUI_VERSION "1.92.4 WIP"
#define IMGUI_VERSION_NUM 19234
#define IMGUI_VERSION_NUM 19236
#define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000
#define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198
#define IMGUI_HAS_VIEWPORT // In 'docking' WIP branch.
@@ -1851,6 +1851,7 @@ enum ImGuiCol_
ImGuiCol_TextSelectedBg, // Selected text inside an InputText
ImGuiCol_TreeLines, // Tree node hierarchy outlines when using ImGuiTreeNodeFlags_DrawLines
ImGuiCol_DragDropTarget, // Rectangle highlighting a drop target
ImGuiCol_UnsavedMarker, // Unsaved Document marker (in window title and tabs)
ImGuiCol_NavCursor, // Color of keyboard/gamepad navigation cursor/rectangle, when visible
ImGuiCol_NavWindowingHighlight, // Highlight window when using CTRL+TAB
ImGuiCol_NavWindowingDimBg, // Darken/colorize entire screen behind the CTRL+TAB window list, when active

View File

@@ -4879,15 +4879,18 @@ static void DemoWindowLayout()
ImGui::Checkbox("Decoration", &enable_extra_decorations);
ImGui::PushItemWidth(ImGui::GetFontSize() * 10);
enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
ImGui::SameLine();
ImGui::Checkbox("Track", &enable_track);
ImGui::PushItemWidth(100);
ImGui::SameLine(140); enable_track |= ImGui::DragInt("##item", &track_item, 0.25f, 0, 99, "Item = %d");
bool scroll_to_off = ImGui::Button("Scroll Offset");
ImGui::SameLine(140); scroll_to_off |= ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
bool scroll_to_off = ImGui::DragFloat("##off", &scroll_to_off_px, 1.00f, 0, FLT_MAX, "+%.0f px");
ImGui::SameLine();
scroll_to_off |= ImGui::Button("Scroll Offset");
bool scroll_to_pos = ImGui::Button("Scroll To Pos");
ImGui::SameLine(140); scroll_to_pos |= ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
bool scroll_to_pos = ImGui::DragFloat("##pos", &scroll_to_pos_px, 1.00f, -10, FLT_MAX, "X/Y = %.0f px");
ImGui::SameLine();
scroll_to_pos |= ImGui::Button("Scroll To Pos");
ImGui::PopItemWidth();
if (scroll_to_off || scroll_to_pos)

View File

@@ -242,6 +242,7 @@ void ImGui::StyleColorsDark(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(1.00f, 1.00f, 1.00f, 1.00f);
colors[ImGuiCol_NavCursor] = ImVec4(0.26f, 0.59f, 0.98f, 1.00f);
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
@@ -309,6 +310,7 @@ void ImGui::StyleColorsClassic(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.00f, 0.00f, 1.00f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(1.00f, 1.00f, 0.00f, 0.90f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.90f, 0.90f, 0.90f, 1.00f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(1.00f, 1.00f, 1.00f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.80f, 0.80f, 0.80f, 0.20f);
@@ -377,6 +379,7 @@ void ImGui::StyleColorsLight(ImGuiStyle* dst)
colors[ImGuiCol_TextSelectedBg] = ImVec4(0.26f, 0.59f, 0.98f, 0.35f);
colors[ImGuiCol_TreeLines] = colors[ImGuiCol_Border];
colors[ImGuiCol_DragDropTarget] = ImVec4(0.26f, 0.59f, 0.98f, 0.95f);
colors[ImGuiCol_UnsavedMarker] = ImVec4(0.00f, 0.00f, 0.00f, 1.00f);
colors[ImGuiCol_NavCursor] = colors[ImGuiCol_HeaderHovered];
colors[ImGuiCol_NavWindowingHighlight] = ImVec4(0.70f, 0.70f, 0.70f, 0.70f);
colors[ImGuiCol_NavWindowingDimBg] = ImVec4(0.20f, 0.20f, 0.20f, 0.20f);

View File

@@ -1578,12 +1578,12 @@ struct ImGuiKeyRoutingData
{
ImGuiKeyRoutingIndex NextEntryIndex;
ImU16 Mods; // Technically we'd only need 4-bits but for simplify we store ImGuiMod_ values which need 16-bits.
ImU8 RoutingCurrScore; // [DEBUG] For debug display
ImU8 RoutingNextScore; // Lower is better (0: perfect score)
ImU16 RoutingCurrScore; // [DEBUG] For debug display
ImU16 RoutingNextScore; // Lower is better (0: perfect score)
ImGuiID RoutingCurr;
ImGuiID RoutingNext;
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 255; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; }
ImGuiKeyRoutingData() { NextEntryIndex = -1; Mods = 0; RoutingCurrScore = RoutingNextScore = 0; RoutingCurr = RoutingNext = ImGuiKeyOwner_NoOwner; }
};
// Routing table: maintain a desired owner for each possible key-chord (key + mods), and setup owner in NewFrame() when mods are matching.
@@ -2511,7 +2511,7 @@ struct ImGuiContext
float NavHighlightActivatedTimer;
ImGuiID NavNextActivateId; // Set by ActivateItemByID(), queued until next frame.
ImGuiActivateFlags NavNextActivateFlags;
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Mouse
ImGuiInputSource NavInputSource; // Keyboard or Gamepad mode? THIS CAN ONLY BE ImGuiInputSource_Keyboard or ImGuiInputSource_Gamepad
ImGuiSelectionUserData NavLastValidSelectionUserData; // Last valid data passed to SetNextItemSelectionUser(), or -1. For current window. Not reset when focusing an item that doesn't have selection data.
ImS8 NavCursorHideFrames;
//ImGuiID NavActivateInputId; // Removed in 1.89.4 (July 2023). This is now part of g.NavActivateId and sets g.NavActivateFlags |= ImGuiActivateFlags_PreferInput. See commit c9a53aa74, issue #5606.
@@ -2691,7 +2691,7 @@ struct ImGuiContext
ImGuiWindow* LogWindow;
ImFileHandle LogFile; // If != NULL log to stdout/ file
ImGuiTextBuffer LogBuffer; // Accumulation buffer when log to clipboard. This is pointer so our GImGui static constructor doesn't call heap allocators.
const char* LogNextPrefix;
const char* LogNextPrefix; // See comment in LogSetNextTextDecoration(): doesn't copy underlying data, use carefully!
const char* LogNextSuffix;
float LogLinePosY;
bool LogLineFirstItem;
@@ -4219,7 +4219,7 @@ extern const char* ImGuiTestEngine_FindItemDebugLabel(ImGuiContext* ctx, ImGuiI
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) if (g.TestEngineHookItems) ImGuiTestEngineHook_ItemInfo(&g, _ID, _LABEL, _FLAGS) // Register item label and status flags (optional)
#define IMGUI_TEST_ENGINE_LOG(_FMT,...) ImGuiTestEngineHook_Log(&g, _FMT, __VA_ARGS__) // Custom log entry from user land into test log
#else
#define IMGUI_TEST_ENGINE_ITEM_ADD(_BB,_ID) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_ADD(_ID,_BB,_ITEM_DATA) ((void)0)
#define IMGUI_TEST_ENGINE_ITEM_INFO(_ID,_LABEL,_FLAGS) ((void)g)
#endif

View File

@@ -3947,6 +3947,7 @@ static ImVec2 InputTextCalcTextSize(ImGuiContext* ctx, const char* text_begin, c
{
ImGuiContext& g = *ctx;
ImGuiInputTextState* obj = &g.InputTextState;
IM_ASSERT(text_end_display >= text_begin && text_end_display <= text_end);
return ImFontCalcTextSizeEx(g.Font, g.FontSize, FLT_MAX, obj->WrapWidth, text_begin, text_end_display, text_end, out_remaining, out_offset, flags);
}
@@ -4327,11 +4328,12 @@ void ImGuiInputTextCallbackData::InsertChars(int pos, const char* new_text, cons
memcpy(Buf + pos, new_text, (size_t)new_text_len * sizeof(char));
Buf[BufTextLen + new_text_len] = '\0';
if (CursorPos >= pos)
CursorPos += new_text_len;
SelectionStart = SelectionEnd = CursorPos;
BufDirty = true;
BufTextLen += new_text_len;
if (CursorPos >= pos)
CursorPos += new_text_len;
CursorPos = ImClamp(CursorPos, 0, BufTextLen);
SelectionStart = SelectionEnd = CursorPos;
}
void ImGui::PushPasswordFont()
@@ -10840,8 +10842,8 @@ void ImGui::TabItemLabelAndCloseButton(ImDrawList* draw_list, const ImRect& bb,
const bool unsaved_marker_visible = (flags & ImGuiTabItemFlags_UnsavedDocument) != 0 && (button_pos.x + button_sz <= bb.Max.x) && (!close_button_visible || !is_hovered);
if (unsaved_marker_visible)
{
const ImRect bullet_bb(button_pos, button_pos + ImVec2(button_sz, button_sz));
RenderBullet(draw_list, bullet_bb.GetCenter(), GetColorU32(ImGuiCol_Text));
ImVec2 bullet_pos = button_pos + ImVec2(button_sz, button_sz) * 0.5f;
RenderBullet(draw_list, bullet_pos, GetColorU32(ImGuiCol_UnsavedMarker));
}
else if (close_button_visible)
{

View File

@@ -7,7 +7,7 @@ Build font atlases using FreeType instead of stb_truetype (which is the default
1. Get latest FreeType binaries or build yourself (under Windows you may use vcpkg with `vcpkg install freetype --triplet=x64-windows`, `vcpkg integrate install`).
2. Add imgui_freetype.h/cpp alongside your project files.
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file
3. Add `#define IMGUI_ENABLE_FREETYPE` in your [imconfig.h](https://github.com/ocornut/imgui/blob/master/imconfig.h) file to make Dear ImGui automatically use the imgui_freetype loader. If your copy Dear ImGui is precompiled, you can always enable imgui_freetype by calling ImFontAtlas::SetFontLoader().
### About Gamma Correct Blending