From ed79b4d22ed2b2ef08ab41be918ad1851325d3d9 Mon Sep 17 00:00:00 2001 From: Max Thrun Date: Wed, 29 May 2019 10:35:41 -0700 Subject: [PATCH] Examples/Backends: Metal: Added support for large meshes (64k+ vertices) with 16-bits indices, enable 'ImGuiBackendFlags_HasVtxOffset' config flag in back-end. (#2591, #2592) --- docs/CHANGELOG.txt | 2 +- examples/imgui_impl_metal.h | 1 + examples/imgui_impl_metal.mm | 11 ++++++----- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ef8e2310..010fc805 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -71,7 +71,7 @@ Other Changes: - Backends: Add native Mac clipboard copy/paste default implementation in core library to match what we are dealing with Win32, and to facilitate integration in custom engines. (#2546) [@andrewwillmott] - Backends: OSX: imgui_impl_osx: Added mouse cursor support. (#2585, #1873) [@actboy168] -- Examples/Backends: DirectX9/10/11/12, Vulkan, OpenGL3 (Desktop GL only): Added support for large meshes +- Examples/Backends: DirectX9/10/11/12, Metal, Vulkan, OpenGL3 (Desktop GL only): Added support for large meshes (64k+ vertices) with 16-bits indices, enable 'ImGuiBackendFlags_RendererHasVtxOffset' in those back-ends. - Examples/Backends: Don't filter characters under 0x10000 before calling io.AddInputCharacter(), the filtering is done in io.AddInputCharacter() itself. This is in prevision for fuller Unicode diff --git a/examples/imgui_impl_metal.h b/examples/imgui_impl_metal.h index f6846851..869c3e52 100644 --- a/examples/imgui_impl_metal.h +++ b/examples/imgui_impl_metal.h @@ -3,6 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. diff --git a/examples/imgui_impl_metal.mm b/examples/imgui_impl_metal.mm index c4947893..f3f1b126 100644 --- a/examples/imgui_impl_metal.mm +++ b/examples/imgui_impl_metal.mm @@ -3,6 +3,7 @@ // Implemented features: // [X] Renderer: User texture binding. Use 'MTLTexture' as ImTextureID. Read the FAQ about ImTextureID in imgui.cpp. +// [X] Renderer: Support for large meshes (64k+ vertices) with 16-bits indices. // You can copy and use unmodified imgui_impl_* files in your project. See main.cpp for an example of using this. // If you are new to dear imgui, read examples/README.txt and read the documentation at the top of imgui.cpp. @@ -10,6 +11,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2019-05-29: Metal: Added support for large mesh (64K+ vertices), enable ImGuiBackendFlags_RendererHasVtxOffset flag. // 2019-04-30: Metal: Added support for special ImDrawCallback_ResetRenderState callback to reset render state. // 2019-02-11: Metal: Projecting clipping rectangles correctly using draw_data->FramebufferScale to allow multi-viewports for retina display. // 2018-11-30: Misc: Setting up io.BackendRendererName so it can be displayed in the About Window. @@ -76,6 +78,7 @@ bool ImGui_ImplMetal_Init(id device) { ImGuiIO& io = ImGui::GetIO(); io.BackendRendererName = "imgui_impl_metal"; + io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ @@ -478,13 +481,10 @@ void ImGui_ImplMetal_DestroyDeviceObjects() for (int n = 0; n < drawData->CmdListsCount; n++) { const ImDrawList* cmd_list = drawData->CmdLists[n]; - ImDrawIdx idx_buffer_offset = 0; memcpy((char *)vertexBuffer.buffer.contents + vertexBufferOffset, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); memcpy((char *)indexBuffer.buffer.contents + indexBufferOffset, cmd_list->IdxBuffer.Data, cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx)); - [commandEncoder setVertexBufferOffset:vertexBufferOffset atIndex:0]; - for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; @@ -522,14 +522,15 @@ void ImGui_ImplMetal_DestroyDeviceObjects() // Bind texture, Draw if (pcmd->TextureId != NULL) [commandEncoder setFragmentTexture:(__bridge id)(pcmd->TextureId) atIndex:0]; + + [commandEncoder setVertexBufferOffset:(vertexBufferOffset + pcmd->VtxOffset * sizeof(ImDrawVert)) atIndex:0]; [commandEncoder drawIndexedPrimitives:MTLPrimitiveTypeTriangle indexCount:pcmd->ElemCount indexType:sizeof(ImDrawIdx) == 2 ? MTLIndexTypeUInt16 : MTLIndexTypeUInt32 indexBuffer:indexBuffer.buffer - indexBufferOffset:indexBufferOffset + idx_buffer_offset]; + indexBufferOffset:indexBufferOffset + pcmd->IdxOffset * sizeof(ImDrawIdx)]; } } - idx_buffer_offset += pcmd->ElemCount * sizeof(ImDrawIdx); } vertexBufferOffset += cmd_list->VtxBuffer.Size * sizeof(ImDrawVert);