ImGuiNET / ImGui.NET

An ImGui wrapper for .NET.
MIT License
1.89k stars 305 forks source link

ImGui.ImageButton putting the application to a crawl. #35

Closed megaweezl closed 7 years ago

megaweezl commented 7 years ago

Hey, just recently set up this project and i'm experimenting a bit with it, when i realized my frames started tanking with just 1 imgui window rendering. First i suspected the rendering, since i didn't put in any work to adjust it to my rendering pipeline, but turns out that the culprit is in the ImGui.ImageButton() call. (removed all rendering calls and frames were still tanking). It drops from the 120frame cap to 100 with 5 imagebuttons, and to 75 with 10 imagebuttons.

I didn't start any intense performance testing, but it appears the ImGui.*Widget calls generally consume quite a lot of time. Can you confirm or deny that?

megaweezl commented 7 years ago

One additional info, since i don't know if it's related:

Managed Debugging Assistant 'PInvokeStackImbalance' : 'A call to PInvoke function 'ImGui.NET!ImGuiNET.ImGuiNative::ImFontAtlas_AddFontDefault' has unbalanced the stack. This is likely because the managed PInvoke signature does not match the unmanaged target signature. Check that the calling convention and parameters of the PInvoke signature match the target unmanaged signature.'

I disabled the PInvokeStackImbalance exception break. I'm not sure what causes the Stack Imbalance to begin with, but i reckon it might contribute to dropping performance.

mellinoe commented 7 years ago

I have not seen anything like this "stack imbalance issue" -- could you give me some more information about your environment? What runtime are you using (.NET Framework, .NET Core, mono, etc.), what OS?

As for ImGui.ImageButton -- it is a very tiny wrapper around the native function, so it should not be particularly slow. This is true for all of the functions here -- they are very, very thin wrappers around imgui itself, so the library's performance is dictated by that.

I will admit that I have only used it in a few places myself, but I didn't notice any tremendous slowdown when doing so. Could you provide any more context for how you are calling ImageButton? Perhaps there is something else that is confounding the measurements.

megaweezl commented 7 years ago

Yeah sure, let's see. Running MSVS2017 15.4.1 on Windows 10. Solution: -Flow --References ---OpenTK 1.0 ---OpenTK.GLControl 1.0 ---ImGui.NET 0.3.0.0 - Build from 17f05b9492e5dce68f7107814ac8ca1b207a52bd - build with imgui 1.51 55a6209931a145dd012e85e6673e5ef6575948c9 and cimgui 1.51 (1df319b2321f704ea058adc81eaafc828b90d3b2) --- System.Numerics - 4.0.0.0 --- System.Numerics.Vectors - 4.1.2.0

The project was a bit weird to set up with nuget. I constantly got a "dll not found exception" on System.Numerics.Vectors, so i set it up manually.

Here's a complete project setup Flow.zip. Sorry for the mess. You can find the exception setting at Debug>Windows>Exception Settings >> Managed Debugging Assistants>PInvokeStackImbalance.

Turns out its not just the ImageButton, that was just when it caught my attention. It actually seems like every ImGui call hits the performance, as you might see in the Dummy Project. Just add more buttons and it will eventually get below 10. (takes around 30 buttons in total)

dpethes commented 7 years ago

As for PInvokeStackImbalance -you use the 32bit version of cimgui, I don't think it has been tested with Imgui.net before. Could you try 64bit?

Edit: How fast is it, when you start it without attached debugger? I get 100+fps on a measly old integrated AMD gpu.

megaweezl commented 7 years ago

Excellent find! The exceptions are gone, and so are the frame drops :) Took me a while to replace and rebuild all my 32bit dependencies but it works fine now.

Thanks for helping out! :D

mellinoe commented 7 years ago

Ah, good catch @dpethes . ImGui.NET should work in a 32-bit app, but the native dependencies here in the repository are 64-bit -- you would need to rebuild them for that to work. But yeah, I haven't tested that either.

dpethes commented 7 years ago

Some more info: cimgui under 32bits builds with cdecl calling convention; in c# the default DllImport convention is stdcall, so for this to work, all imports would need to specify CallingConvention=CallingConvention.Cdecl.

mellinoe commented 7 years ago

Interestingly, the PInvokes work as-is on 32-bit .NET Core. The debugger may just not be reporting the stack imbalance on .NET Core, though. I do see the stack imbalance when I run on 32-bit .NET Framework (and VS pops up some errors), so I pushed a commit to fix that.

mellinoe commented 7 years ago

Thanks for the report @megaweezl . This should be fixed now.