husker-dev / openglfx

OpenGL node for JavaFX
Apache License 2.0
88 stars 12 forks source link

Is Async already triple buffered? Why does the async tag cause rendering artifacts? #84

Open jodysowald opened 1 week ago

jodysowald commented 1 week ago

Is Async already triple buffered? Why does the async tag cause rendering artifacts? I've read https://github.com/husker-dev/openglfx/issues/41 and understand why the async tag was added. I've tried it and seen varied performance. Generally great results for me as my render is slow, but i overlay JFX components and that is quite buggy as you can see the redrawn regions.

I've been considering adding a direct https://github.com/husker-dev/grapl dep to my project to Impl multi-thread triple buffering myself and turning off the async tag so that i can get the async performance and keep correctly JFX component rendering on top.

So I suppose I have two or three questions.

  1. What causes the JFX artifacts when rendered on top of the OpenGLFX control with async on? a. Do you know what I am referring to there? The bounding rectangle invalidation/render area around elements is always visually a frame behind the OpenGLFX render when async is on.

  2. Is async implemented as double or triple buffering? a. If it is not triple buffered, have you considered triple buffering options for the openglfx panel?

  3. While I believe that I understand OpenGL contexts enough to implement triple buffering I haven't done it before and keep seeing lots of warnings from people about it being hard to get right. Is there anything technically preventing me from using OpenGLFX with async off and my own thread with grapl together to implement triple buffering into the OpenGLFX panel?

The main reason I am looking for triple buffering with async off is because I have ~8 draw calls with a VBO change each. They are fundamentally different data structures and each is handling its own multi-draws/instances. This alone is causing me enough latency to be problematic for smooth rendering and I am getting habitual frame stutter from the latency. Given java's latency to call native methods the other thing i was considering was a single native call into my own native lib which executes all of my render/vbo/uniform changes at once, that would be far from ideal so i'm looking for other ways to remove my render speed issues.

husker-dev commented 1 week ago
  1. JavaFX can create artifacts due to such a thing as "dirty regions". In order to update some part of the window, JavaFX requires exactly parts. Openglfx canvas uses special marking function, but only when redrawing the entire canvas. As I understand it, some elements on top can conflict with it, and cause such artifacts. I'll see what I can do about it when I have time.

  2. In the release version (4.0.5), Async rendering is done using some dirty thread synchronization. This is a very bad solution, so in the master branch I changed it to frame buffering - it is also possible to specify the required number of buffers. With one buffer it will be the same as "Sync", and with two or more is "Async". You can try to compile the code from the master branch and test it. I am very busy at work in the next month, so I can not find time to complete everything that is planned.

  3. The built-in double buffering only works with physical windows, when calling swapBuffers. With offscreen contexts you will have to make your own implementation.

You can try to create shared context in a separate thread. After rendering, you can draw it into a shared buffer, and display it in openglfx. It may require some synchronisation too.

jodysowald commented 1 week ago

Thank you very much. You always respond quickly and I appreciate that. I may build master myself or try to impl my own triple buffer soon

  1. Async is already nearly performant enough for me but the render artifacts rule it out, I may still need to investigate ways to lower my java<->native latency per the number of calls I'm making. but due to JavaFX/OpenGL issues I cannot profile my render with Nvidia Insight to be sure that most of my latency comes from interop rather than render time. That said RenderDoc does offer me some speed information that is probably sufficient for me for now. I know OpenGL has some built in function for checking render times and I may look into those next to confirm.

  2. Gotcha. So the current Master branch implements Async differently? I may try that.