-
-
Notifications
You must be signed in to change notification settings - Fork 10.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Remote network access/viewer #75
Comments
In my opinion you should put this in a separate project. |
The idea is to make as simple as possible, to the core C++ side might end up being one or two functions ideally and then it wouldn't hurt just putting it inside. I'll see how it goes if/when that thing happen. I'll have to try doing it someday. |
Jordi sent me a demo client It's not ready for two reason
|
Perhaps Webby https://github.com/deplinenoise/webby by @deplinenoise can be used for the web socket stuff? |
That's perfect. Jordi managed to largely simplify the setup using Webby now. Still massaging the system but I managed to compile and run here (albeit bit of a tricky setup but getting better) |
That's the github for Jordi's stuff by the way |
I think this is a great idea, but it could be addressed in a more fundamental fashion. Instead of sending vertex lists and io, an ImGui wire protocol should be defined. It would express ImGui widgets as fragments of data packets (can use msgpack/protobuf). The same with io. |
Yes it makes sense to formalize those transfers into a protocol. But the data transfers are so trivial at the moment it isn't really a priority at the moment. I am not sure there is a need to take it down to the "widget" level. By definition and design all logic and inputs can only be processed as the functions are called, so the "output" will always be mostly visual. Note that the remoteimgui implementation at https://github.com/JordiRos/remoteimgui already pretty much work. It could / should probably be made more optimal later on. Whatever technique we find work best could be turned into an official protocol. As this system mature I imagine more things will be passed down the protocol (perhaps information about which command-list represent which windows). We'll have to see how it matures. |
The reason about why the host-side "renderer" needs information about individual windows is that I imagine we can turn the system into a multiscreen canvas where you can move the display window from the host to a remote client and vice-versa. For performance reason it would make sense to not transmit the windows that aren't visible to remote. (and similarly not attempt to render .the remote-only windows locally). Doing that per-window will probably be more efficient than doing it per-vertice. |
If I understand correctly you too suggest that the protocol should be organized around widgets/windows? I would like to give some examples. I have an application that needs a "debug terminal", however, it is not necesarily able to produce acceptable OpenGL/DirectX output, nor it is convenient to compile with C++ code. So, instead of, say writing the following C++ code:
I could send a message like:
(The code got a bit clumsy on a mobile, sorry). |
Well you can send the vertex buffers for remote rendering on a platform that can render it, it would work. If you cannot compile C++ you are out of luck. Adding this sort of protocol would hinder imgui design and development rather severely. However one could always create a library that turns this input into imgui calls. |
Have you considered using the RFB protocol (here's an implementation) to send screen diffs to a viewer application? I might give it a try, but how can I render ImGui to a software framebuffer? |
I haven't looked into any of that but I suspect we should be sending
My gut feeling is that this approach would be lighter than send screen diffs or dealing with software rendering. |
I imagine ImGui could be drawn onto a framebuffer, which the embedded VNC server could then read into main RAM, diff it, and send whatever it needs to send to the client, so the rendering would still occur on the GPU. Since VNC only sends changes, I don't think it would be heavier than sending draw list changes. For now I'm playing with something along the lines of what @dkrikun described, but only for a very limited subset of ImGui widgets. |
Sending via VNC is very heavy weight VS remoting the API calls! VNC just looks bit of an image that changed and sends them, it can be very CPU and bandwidth heavy. |
VNC only sends diffs and has some encodings to reduce network traffic in exchange of higher CPU utilization, but yes, it's heavy weight when compared with a higher level interface. What it brings to the table is the possibility of having a remote ImGui application with very little effort. |
Sending the vertex buffer with some obvious optimization a like the ones listed by @ocornut is much more performant than any bitmap or pixel based approach. Quality is also superior because you don't compress anything and line/polygons rendering is 100% accurate and sharp with antialias and all . Additionally you can generate retina resolution textures for clients that can display them, so that you can see the remoted interface at 2X resolution even if the native application runs on a low res monitor. |
Again, I agree, I'm just saying that VNC could provide a working solution very quickly. |
On python there, the VisPy project has made a standard, they use for sending opengl across the network. https://github.com/vispy/vispy/wiki/Spec.-GLIR You could then use their WebGL renderer on the browser end. |
Here is yet another attempt to stream ImGui DrawData over WebSockets: https://github.com/ggerganov/imgui-ws To reduce network traffic I send the full DrawData upon client connection and then send only the difference between the current DrawData and the previous one. The diffs are additionally run-length encoded and on top of that, if supported by the browser, WebSocket compression is applied. But more improvements can be made for sure. Another thing I found convenient is to give the client an option to control the rate at which the DrawData updates are sent to them from the server. This can be useful in cases where 60FPS stream is note required and it helps reduce bandwidth and CPU usage. |
Thanks for posting this @ggerganov ! This is looking good. Some ideas:
(As a minor request, could you try using the full term "Dear ImGui" whenever possible in documentation, rather than "ImGui"? Thanks!) |
Closing this general purpose thread (OLDEST OPEN THREAD) as there are various solutions at If new one appears we'll also mention them here for completeness. |
(Edit 2020: See https://github.com/ocornut/imgui/wiki/Useful-Extensions#remoting)
An idea I had in mind for a bit - recently people at my previous workplace started implementing something along the same line so I'd thought I'd describe the idea here.
Implement a way for ImGui to export its output to a client on the network (likely local network). The client would display the UI and feed back mouse/keyboard inputs. This would be useful to save screen real-estate on the host.
Jordi at Media Molecule has been working on a web client to do that:
The "simple" implementation of that would be to be sending vertex buffers along the network.
Pros:
Cons
Aside from that the application or protocol needs a way to
And we need to implement a client. Jordi's approach to create a web based client using webgl sounds like a good approach to me.
Based on this idea it looks like the amount of vertex data may be the bottleneck.
a) Obviously we need to compress data. we need a compressor that is efficient and "imgui" friendly in the sense that ideally it would be added to ImGui.cpp without doubling its size. we also need a suitable decompressor on the client side (javascript if we are aiming for a web client).
b) Split the stream for each ImDrawList (corresponding to each window) and only send a diff of the data. Need to look for a diff engine. The imgui code would be able to place extra marker based on the layout to minimize the diff size if it can help.
c) Deinterleave the stream (e.g store all x position, then all y position, then all colors, etc.) + store everything as delta from the previous vertex. This will make operations such as moving a window very cheap (only the first vertex will change). Will result in lots of zeros (highly compressible) or patterns using value within close range.
d) Use indexed triangles or quads. Currently Imgui uses non-indexed triangles to simplify the implementation of the ImDrawList renderer but it isn't optimal when it comes to data size.
A combination of those things hopefully can get the data small enough to work over local network.
The text was updated successfully, but these errors were encountered: