Can JavaFX do CAD?
richard.bair at oracle.com
Wed Jul 24 12:06:16 PDT 2013
That would be terrific. In answer to Fabrizio's question, it depends. What kinds of nodes, and what is their cost to render.
It would be interesting to get some bounded sizes. I had gathered some of this information ages ago in an ad-hoc way, it would be good to have some kind of repeatable tests to measure these things. But for example, how many rectangles or images can you have in a scene graph before it gets too slow? Wide tree, tall tree, or balanced tree? Most of the times people are doing a bazillion nodes though it always seems to come down to paths, and those are probably our worst case.
In order to render paths (that look good) the first thing we do is generate a mask for the path which tells us how to anti-alias the path. And we always anti-alias, whereas in J2D (iirc) you can tell it to do no anti-aliasing. Once we have the mask we then have to send the mask to the graphics card, and since each path is different, it is going to be a different mask for each path. And then the shader will draw the path blistering fast. It just took a long time to load the texture on the card and every path is a different texture which also means a state change on the card.
I filed an RFE a little while ago for a "LineGroup" or something like that (I don't remember what I called it). But basically it is supposed to be a Shape which is just a bunch of independent lines. You could draw them much like a path with line-to's, but instead of generating a single path. But you'd still have problems when it comes to performance if we end up having to send down multiple textures for lines of different orientations / lengths.
Maybe if we had a mode for turning off AA it would help with lots of paths.
But besides the rendering cost, there are two other costs. One is the cost of producing bounding rectangles for all of the nodes. We need these so we can do picking, and do dirty-region computation (figure out, if only a handful of things have changed, what clip to use so we can avoid drawing everything in the scene). It could be that we could optimize this so that if a branch doesn't have any listeners we could avoid generating the bounding rectangle (or bounding volume for a 3D node), except that we still need it for dirty opts unless you had a way to disable it for a subset of the scene.
There is also the memory cost. Because Property objects are fairly heavy and because we use a *lot* of them and every node has a lot of properties, Nodes are not lightweight. Even though we've taken steps to "bucketize" the properties and hide them behind a helper object so we only instantiate the properties if they're used, the Node still has some basic costs that are not that cheap. For example, we have several transforms that we maintain -- boundsInLocal, layoutBounds, boundsInParent. And we don't maintain these just on Node but also on the NGNode peer. We have to do this because we run the render thread separate from the FX thread which gives us greater performance at the cost of memory (by having to duplicate state so the background thread can safely render while the FX thread is processing the next frame).
So, things I have in my mind whenever the question of a large scene comes up (but which I don't have bandwidth to chase down on my own, but for which somebody in the community could chase down and I'd be happy to provide consulting as necessary on this list):
- What is the minimum size of a Node (including NGNode), and where is the memory being used
- Would we benefit from a "full lazy" model for properties where we only instantiate them if somebody adds a listener
- Are there options for making Node smaller without hurting performance (fps)?
- What are our algorithms tailored for: wide scenes, tall scenes, or balanced scenes?
- What is the "normal" scene -- tall or wide or balanced?
- What is the relative cost of rendering different types of nodes?
- What would need to be done to make path rendering more efficient? Is it a matter of SPEED / QUALITY tradeoffs?
Maybe also, do we need a type of node that takes PathElements which have their own fills? Their own strokes? Basically a Shape but without all the Node-isms like CSS / layout / events. Something where you could have millions of primitives, but they aren't Nodes because they don't need to be interactive, but they're just a bunch of vector artwork that needs to be drawn?
We talked years ago about having a "compressed" view of paths, such that you could take some SVG and express it as a compact bunch of bytes that were passed to the graphics layer to draw, instead of them all being nodes. We also have talked about having a way to "compress" some graph of nodes into a single opaque node that would do all that other drawing stuff behind the scenes. In this way the scene graph costs are removed (for determining bounds and such) or at least diminished, and all we're left with is rendering costs.
On Jul 24, 2013, at 11:04 AM, Scott Palmer <swpalmer at gmail.com> wrote:
> Because my document is zoomable, I used the same approach SVG->FXML to represent some icons that are used on items throughout the document. This works but I have always felt that it is too heavy for my use-case. Specially since I have the same icon appearing in multiple places, which means I need to reproduce the same node structure in each place instead of using a simple and fast image. I have it on my list to investigate a mechanism to replace these with something that renders the appropriately scaled shapes once to an image that can be re-used by ImageView nodes instead of the duplicating the entire node hierarchy for the shape.
> I should put some debug code in my app to count the nodes in the scene graph to get an idea of when the system gets too bogged down.
> On Wed, Jul 24, 2013 at 11:39 AM, Fabrizio Giudici <Fabrizio.Giudici at tidalwave.it> wrote:
> On Wed, 24 Jul 2013 17:06:57 +0200, Richard Bair <richard.bair at oracle.com> wrote:
> The scene graph will not support millions of nodes,
> How many nodes are supported? I'm helping with the prototyping of a software that should render 2D SVG. In the past the need was for relatively complex documents, converted from 2D AutoCAD - the need was to render everything smoothly, zoom in & out, having less than a hundred additional nodes inserted programmatically that require an interaction - animation, context menu, etc. Only the additional nodes needed interaction and editing, the other stuff just to be rendered quickly. In the past we did with Batik+Swing, and it was pretty good in the end - no problems with the performance.
> Now we're trying a pure JavaFX approach and we're using the tool provided by Toni Eppleton that converts SVG to FXML. In the new project the SVG documents are simpler, still we needed to simplify them (e.g. smoothing some curves - they represent geographic borders) for having a good performance. We didn't measure anything so far - just trying - also because after the smoothing the speed is ok for the new project. But I'm wondering whether a port of the old project with Batik would be feasible.
> Fabrizio Giudici - Java Architect @ Tidalwave s.a.s.
> "We make Java work. Everywhere."
> http://tidalwave.it/fabrizio/blog - fabrizio.giudici at tidalwave.it
More information about the openjfx-dev