From e94f95d82b94b36dfd0a3b217787ab7cb638d01a Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 7 Oct 2024 21:00:07 +0200 Subject: [PATCH] Backends: DX11, DX12, Vulkan, WGPU: Expose some backend-specific render state usable for callbacks. (#6969, #5834, #7468, #3590) --- backends/imgui_impl_dx11.cpp | 11 +++++++++++ backends/imgui_impl_dx11.h | 12 ++++++++++++ backends/imgui_impl_dx12.cpp | 10 ++++++++++ backends/imgui_impl_dx12.h | 10 ++++++++++ backends/imgui_impl_vulkan.cpp | 11 +++++++++++ backends/imgui_impl_vulkan.h | 31 +++++++++++++++++++++---------- backends/imgui_impl_wgpu.cpp | 10 ++++++++++ backends/imgui_impl_wgpu.h | 10 ++++++++++ docs/CHANGELOG.txt | 6 ++++++ imgui.h | 9 ++++++++- 10 files changed, 109 insertions(+), 11 deletions(-) diff --git a/backends/imgui_impl_dx11.cpp b/backends/imgui_impl_dx11.cpp index f656bbc55..4ee774085 100644 --- a/backends/imgui_impl_dx11.cpp +++ b/backends/imgui_impl_dx11.cpp @@ -4,6 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -15,6 +16,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-10-07: DirectX11: Expose selected render state in ImGui_ImplDX11_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 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) @@ -246,6 +248,14 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) // Setup desired DX state ImGui_ImplDX11_SetupRenderState(draw_data, device); + // Setup render state structure (for callbacks and custom texture bindings) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplDX11_RenderState render_state; + render_state.Device = bd->pd3dDevice; + render_state.DeviceContext = bd->pd3dDeviceContext; + render_state.SamplerDefault = bd->pFontSampler; + platform_io.Renderer_RenderState = &render_state; + // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_idx_offset = 0; @@ -287,6 +297,7 @@ void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data) global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + platform_io.Renderer_RenderState = NULL; // Restore modified DX state device->RSSetScissorRects(old.ScissorRectsCount, old.ScissorRects); diff --git a/backends/imgui_impl_dx11.h b/backends/imgui_impl_dx11.h index cde64ee96..cb79633c3 100644 --- a/backends/imgui_impl_dx11.h +++ b/backends/imgui_impl_dx11.h @@ -4,6 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'ID3D11ShaderResourceView*' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -19,6 +20,7 @@ struct ID3D11Device; struct ID3D11DeviceContext; +struct ID3D11SamplerState; // 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); @@ -30,4 +32,14 @@ IMGUI_IMPL_API void ImGui_ImplDX11_RenderDrawData(ImDrawData* draw_data); IMGUI_IMPL_API void ImGui_ImplDX11_InvalidateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplDX11_CreateDeviceObjects(); +// [BETA] Selected render state data shared with callbacks. +// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX11_RenderDrawData() call. +// (Please open an issue if you feel you need access to more data) +struct ImGui_ImplDX11_RenderState +{ + ID3D11Device* Device; + ID3D11DeviceContext* DeviceContext; + ID3D11SamplerState* SamplerDefault; +}; + #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_dx12.cpp b/backends/imgui_impl_dx12.cpp index c63503cc0..376ab7a68 100644 --- a/backends/imgui_impl_dx12.cpp +++ b/backends/imgui_impl_dx12.cpp @@ -4,6 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. @@ -23,6 +24,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-10-07: DirectX12: Expose selected render state in ImGui_ImplDX12_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 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: DirectX12: Replaced direct access to ImDrawCmd::TextureId with a call to ImDrawCmd::GetTexID(). (will become a requirement) @@ -245,6 +247,13 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL // Setup desired DX state ImGui_ImplDX12_SetupRenderState(draw_data, command_list, fr); + // Setup render state structure (for callbacks and custom texture bindings) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplDX12_RenderState render_state; + render_state.Device = bd->pd3dDevice; + render_state.CommandList = command_list; + platform_io.Renderer_RenderState = &render_state; + // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_vtx_offset = 0; @@ -287,6 +296,7 @@ void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3D12GraphicsCommandL global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + platform_io.Renderer_RenderState = NULL; } static void ImGui_ImplDX12_CreateFontsTexture() diff --git a/backends/imgui_impl_dx12.h b/backends/imgui_impl_dx12.h index 08c0a1255..bee7454fa 100644 --- a/backends/imgui_impl_dx12.h +++ b/backends/imgui_impl_dx12.h @@ -4,6 +4,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'D3D12_GPU_DESCRIPTOR_HANDLE' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // Important: to compile on 32-bit systems, this backend requires code to be compiled with '#define ImTextureID ImU64'. // See imgui_impl_dx12.cpp file for details. @@ -42,4 +43,13 @@ IMGUI_IMPL_API void ImGui_ImplDX12_RenderDrawData(ImDrawData* draw_data, ID3 IMGUI_IMPL_API void ImGui_ImplDX12_InvalidateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplDX12_CreateDeviceObjects(); +// [BETA] Selected render state data shared with callbacks. +// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplDX12_RenderDrawData() call. +// (Please open an issue if you feel you need access to more data) +struct ImGui_ImplDX12_RenderState +{ + ID3D12Device* Device; + ID3D12GraphicsCommandList* CommandList; +}; + #endif // #ifndef IMGUI_DISABLE diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index a0df9edfb..f3f560607 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -4,6 +4,7 @@ // Implemented features: // [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions. // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'. // This is because we need ImTextureID to carry a 64-bit value and by default ImTextureID is defined as void*. @@ -33,6 +34,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-10-07: Vulkan: Expose selected render state in ImGui_ImplVulkan_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-04-19: Vulkan: Added convenience support for Volk via IMGUI_IMPL_VULKAN_USE_VOLK define (you can also use IMGUI_IMPL_VULKAN_NO_PROTOTYPES + wrap Volk via ImGui_ImplVulkan_LoadFunctions().) // 2024-02-14: *BREAKING CHANGE*: Moved RenderPass parameter from ImGui_ImplVulkan_Init() function to ImGui_ImplVulkan_InitInfo structure. Not required when using dynamic rendering. // 2024-02-12: *BREAKING CHANGE*: Dynamic rendering now require filling PipelineRenderingCreateInfo structure. @@ -540,6 +542,14 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm // Setup desired Vulkan state ImGui_ImplVulkan_SetupRenderState(draw_data, pipeline, command_buffer, rb, fb_width, fb_height); + // Setup render state structure (for callbacks and custom texture bindings) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplVulkan_RenderState render_state; + render_state.CommandBuffer = command_buffer; + render_state.Pipeline = pipeline; + render_state.PipelineLayout = bd->PipelineLayout; + platform_io.Renderer_RenderState = &render_state; + // Will project scissor/clipping rectangles into framebuffer space ImVec2 clip_off = draw_data->DisplayPos; // (0,0) unless using multi-viewports ImVec2 clip_scale = draw_data->FramebufferScale; // (1,1) unless using retina display which are often (2,2) @@ -602,6 +612,7 @@ void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer comm global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + platform_io.Renderer_RenderState = NULL; // Note: at this point both vkCmdSetViewport() and vkCmdSetScissor() have been called. // Our last values will leak into user/application rendering IF: diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 1c7f76951..a834d7d7a 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -4,6 +4,7 @@ // Implemented features: // [!] Renderer: User texture binding. Use 'VkDescriptorSet' as ImTextureID. Read the FAQ about ImTextureID! See https://github.com/ocornut/imgui/pull/914 for discussions. // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // Important: on 32-bit systems, user texture binding is only supported if your imconfig file has '#define ImTextureID ImU64'. // See imgui_impl_vulkan.cpp file for details. @@ -99,23 +100,33 @@ struct ImGui_ImplVulkan_InitInfo }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! -IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); -IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); -IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); -IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); -IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontsTexture(); -IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) +IMGUI_IMPL_API bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info); +IMGUI_IMPL_API void ImGui_ImplVulkan_Shutdown(); +IMGUI_IMPL_API void ImGui_ImplVulkan_NewFrame(); +IMGUI_IMPL_API void ImGui_ImplVulkan_RenderDrawData(ImDrawData* draw_data, VkCommandBuffer command_buffer, VkPipeline pipeline = VK_NULL_HANDLE); +IMGUI_IMPL_API bool ImGui_ImplVulkan_CreateFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplVulkan_DestroyFontsTexture(); +IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_image_count); // To override MinImageCount after initialization (e.g. if swap chain is recreated) // Register a texture (VkDescriptorSet == ImTextureID) // FIXME: This is experimental in the sense that we are unsure how to best design/tackle this problem // Please post to https://github.com/ocornut/imgui/pull/914 if you have suggestions. -IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); -IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set); +IMGUI_IMPL_API VkDescriptorSet ImGui_ImplVulkan_AddTexture(VkSampler sampler, VkImageView image_view, VkImageLayout image_layout); +IMGUI_IMPL_API void ImGui_ImplVulkan_RemoveTexture(VkDescriptorSet descriptor_set); // Optional: load Vulkan functions with a custom function loader // This is only useful with IMGUI_IMPL_VULKAN_NO_PROTOTYPES / VK_NO_PROTOTYPES -IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr); +IMGUI_IMPL_API bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data = nullptr); + +// [BETA] Selected render state data shared with callbacks. +// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplVulkan_RenderDrawData() call. +// (Please open an issue if you feel you need access to more data) +struct ImGui_ImplVulkan_RenderState +{ + VkCommandBuffer CommandBuffer; + VkPipeline Pipeline; + VkPipelineLayout PipelineLayout; +}; //------------------------------------------------------------------------- // Internal / Miscellaneous Vulkan Helpers diff --git a/backends/imgui_impl_wgpu.cpp b/backends/imgui_impl_wgpu.cpp index 9f75364d5..84a28406b 100644 --- a/backends/imgui_impl_wgpu.cpp +++ b/backends/imgui_impl_wgpu.cpp @@ -5,6 +5,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -16,6 +17,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2024-10-07: Expose selected render state in ImGui_ImplWGPU_RenderState, which you can access in 'void* platform_io.Renderer_RenderState' during draw callbacks. // 2024-09-16: Added support for optional IMGUI_IMPL_WEBGPU_BACKEND_DAWN / IMGUI_IMPL_WEBGPU_BACKEND_WGPU define to handle ever-changing native implementations. (#7977) // 2024-01-22: Added configurable PipelineMultisampleState struct. (#7240) // 2024-01-22: (Breaking) ImGui_ImplWGPU_Init() now takes a ImGui_ImplWGPU_InitInfo structure instead of variety of parameters, allowing for easier further changes. @@ -439,6 +441,13 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder // Setup desired render state ImGui_ImplWGPU_SetupRenderState(draw_data, pass_encoder, fr); + // Setup render state structure (for callbacks and custom texture bindings) + ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); + ImGui_ImplWGPU_RenderState render_state; + render_state.Device = bd->wgpuDevice; + render_state.RenderPassEncoder = pass_encoder; + platform_io.Renderer_RenderState = &render_state; + // Render command lists // (Because we merged all buffers into a single one, we maintain our own offset into them) int global_vtx_offset = 0; @@ -497,6 +506,7 @@ void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURenderPassEncoder global_idx_offset += draw_list->IdxBuffer.Size; global_vtx_offset += draw_list->VtxBuffer.Size; } + platform_io.Renderer_RenderState = NULL; } static void ImGui_ImplWGPU_CreateFontsTexture() diff --git a/backends/imgui_impl_wgpu.h b/backends/imgui_impl_wgpu.h index e6835dee9..a171fd6d0 100644 --- a/backends/imgui_impl_wgpu.h +++ b/backends/imgui_impl_wgpu.h @@ -12,6 +12,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'WGPUTextureView' as ImTextureID. Read the FAQ about ImTextureID! // [X] Renderer: Large meshes support (64k+ vertices) with 16-bit indices. +// [X] Renderer: Expose selected render state for draw callbacks to use. Access in '(ImGui_ImplXXXX_RenderState*)platform_io.BackendRendererRenderState'. // You can use unmodified imgui_impl_* files in your project. See examples/ folder for examples of using this. // Prefer including the entire imgui/ repository into your project (either as a copy or as a submodule), and only build the backends you need. @@ -54,4 +55,13 @@ IMGUI_IMPL_API void ImGui_ImplWGPU_RenderDrawData(ImDrawData* draw_data, WGPURen IMGUI_IMPL_API void ImGui_ImplWGPU_InvalidateDeviceObjects(); IMGUI_IMPL_API bool ImGui_ImplWGPU_CreateDeviceObjects(); +// [BETA] Selected render state data shared with callbacks. +// This is temporarily stored in io.BackendRendererRenderState during the ImGui_ImplWGPU_RenderDrawData() call. +// (Please open an issue if you feel you need access to more data) +struct ImGui_ImplWGPU_RenderState +{ + WGPUDevice Device; + WGPURenderPassEncoder RenderPassEncoder; +}; + #endif // #ifndef IMGUI_DISABLE diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index b5f526809..4ca534c7b 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -43,6 +43,12 @@ Breaking changes: Other changes: +- IO: added 'void* platform_io.Renderer_RenderState' which is set during the + ImGui_ImplXXXX_RenderDrawData() of standard backend to expose selected render + state to draw callbacks. (#6969, #5834, #7468, #3590) +- Backends: DX11, DX12, Vulkan, WGPU: expose selected state in ImGui_ImplXXXX_RenderState. + structure during render loop. (#6969, #5834, #7468, #3590) + ----------------------------------------------------------------------- VERSION 1.91.3 (Released 2024-10-04) diff --git a/imgui.h b/imgui.h index 49ad70cee..f3d5d83d4 100644 --- a/imgui.h +++ b/imgui.h @@ -3515,7 +3515,7 @@ struct ImGuiPlatformIO IMGUI_API ImGuiPlatformIO(); //------------------------------------------------------------------ - // Input - Interface with OS/backends + // Interface with OS and Platform backend //------------------------------------------------------------------ // Optional: Access OS clipboard @@ -3538,6 +3538,13 @@ struct ImGuiPlatformIO // Optional: Platform locale // [Experimental] Configure decimal point e.g. '.' or ',' useful for some languages (e.g. German), generally pulled from *localeconv()->decimal_point ImWchar Platform_LocaleDecimalPoint; // '.' + + //------------------------------------------------------------------ + // Interface with Renderer Backend + //------------------------------------------------------------------ + + // Written by some backends during ImGui_ImplXXXX_RenderDrawData() call to point backend_specific ImGui_ImplXXXX_RenderState* structure. + void* Renderer_RenderState; }; // (Optional) Support for IME (Input Method Editor) via the platform_io.Platform_SetImeDataFn() function.