Canvas performance on Mac OS

Jim Graham james.graham at oracle.com
Wed Apr 8 00:23:44 UTC 2015


If I modify the Sierpinksi program to use moveTo/lineTo/lineTo on a path 
and fill the entire path at once the performance improves dramatically 
on both Intel and nVidia GPUs. It is faster still if I replace the 
triangles with fillRect calls, but not by as large a margin. It would 
appear that we are getting entirely bogged down by uploading lots of 
little alpha coverage tiles for each individual polygon to the GPU (odd 
that this overhead would be greater for the Intel integrated graphics 
that uses main system RAM than the nVidia discrete graphics which uses a 
separate memory system, but there could be something to be said for the 
discrete VRAM being faster).

...jim

On 3/31/15, 1:31 PM, Chris Newland wrote:
> Hi Jim,
>
> Thanks, that makes things much clearer.
>
> I was surprised how much was going on under the hood of GraphicsContext
> and hoped it was just magic glue that gave the best of GPU acceleration
> where available and immediate-mode-like simple rasterizing where not.
>
> I've managed to find an anomaly with GraphicsContext.fillPolygon where the
> software pipeline achieves the full 60fps but ES2 can only manage
> 30-35fps. It uses lots of overlapping filled triangles so I expect suffers
> from the problem you've described.
>
> SSCCE:
> https://github.com/chriswhocodes/DemoFX/blob/master/src/main/java/com/chrisnewland/demofx/standalone/Sierpinski.java
>
> Was full frame rate canvas drawing an expected use case for JavaFX or
> would I be better off with Graphics2D?
>
> Thanks,
>
> Chris
>
> On Mon, March 30, 2015 20:04, Jim Graham wrote:
>> Hi Chris,
>>
>>
>> drawLine() is a very simple primitive that can be optimized with a GPU
>> shader.  It either looks like a (potentially rotated) rectangle or a
>> rounded rect - and we have optimized shaders for both cases.  A large
>> number of drawLine() calls turns into simply accumulating a large vertex
>> list and uploading it to the GPU with an appropriate shader which is very
>> fast.
>>
>> drawPolygon() is a very complex operation that involves things like:
>>
>> - dealing with line joins between segments that don't exist for
>> drawLine() - dealing with only rendering common points of intersection
>> once
>>
>> To handle all of that complexity we have to involve a rasterizer that
>> takes the entire collection of lines, analyzes the stroke attributes and
>> interactions and computes a coverage mask for each pixel in the region. We
>> do that in software currently for all pipelines.
>>
>> For the ES2 pipeline Line.v.Poly is dominated by pure GPU vs CPU path
>> rasterization.
>>
>> For the SW pipeline, drawLine is a simplified case of drawPolygon and so
>> the overhead of lots of calls to drawLine() dominates its performance.
>>
>> I would expect ES2 to blow the SW pipeline out of the water with
>> drawLine() performance (as long as there are no additional rendering
>> primitives interspersed in the set of lines).
>>
>> But, both should be on the same footing for the drawPolygon case.  Does
>> the ES2 pipeline compare similarly (hopefully better than) the SW pipeline
>> for the polygon case?
>>
>> One thing I noticed is that we have no optimized case for drawLine() on
>> the SW pipeline.  It generates a path containing a single MOVETO and LINETO
>> and feeds it to the generalized path rasterizer when it could instead
>> compute the rounded/square rectangle and render it more directly.  If we
>> added that support then I'd expect the SW pipeline to perform the set of
>> drawLine calls faster than drawPolygon as well...
>>
>> ...jim
>>
>>
>> On 3/28/15 3:22 AM, Chris Newland wrote:
>>
>>> Hi Robert,
>>>
>>>
>>> I've not filed a Jira yet as I was hoping to find time to investigate
>>> thoroughly but when I saw your question I thought I'd better add my
>>> findings.
>>>
>>> I believe the issue is in the ES2Pipeline as if I run with
>>> -Dprism.order=sw then strokePolygon outperforms the series of strokeLine
>>>   commands as expected:
>>>
>>> java -cp target/DemoFX.jar -Dprism.order=sw
>>> com.chrisnewland.demofx.DemoFXApplication -c 500 -m line Result: 44fps
>>>
>>>
>>> java -cp target/DemoFX.jar -Dprism.order=sw
>>> com.chrisnewland.demofx.DemoFXApplication -c 500 -m poly Result: 60fps
>>>
>>>
>>> Will see if I can find the root cause as I've got plenty more examples
>>> where ES2Pipeline performs horribly on my Mac which should have no
>>> problem throwing around a few thousand polys.
>>>
>>> I realise there's a *lot* of indirection involved in making JavaFX
>>> support such a wide range of underlying graphics systems but I do think
>>> there's a bug here.
>>>
>>> Will file a Jira if I can contribute a bit more than "feels slow" ;)
>>>
>>>
>>> Cheers,
>>>
>>>
>>> Chris
>>>
>>>
>>> On Sat, March 28, 2015 10:06, Robert Krüger wrote:
>>>
>>>> This is consistent with what I am observing. Is this something that
>>>> Oracle
>>>> is aware of? Looking at Jira, I don't see that anyone is working on
>>>> this:
>>>>
>>>>
>>>> https://javafx-jira.kenai.com/issues/?jql=status%20in%20(Open%2C%20%2
>>>> 2In%
>>>> 20Progress%22%2C%20Reopened)%20AND%20labels%20in%20(macosx)%20%20AND%2
>>>> 0la
>>>> bels%20in%20(performance)
>>>>
>>>> Given that one of the One of the main reasons to use JFX for me is to
>>>> be able to develop with one code base for at least OSX and Windows and
>>>> the official statement what JavaFX is for, i.e.
>>>>
>>>> "JavaFX is a set of graphics and media packages that enables
>>>> developers to design, create, test, debug, and deploy rich client
>>>> applications that operate consistently across diverse platforms"
>>>>
>>>> and the fact that this is clearly not the case currently (8u40) as
>>>> soon as I do something else than simple forms, I run into
>>>> performance/quality problems on the Mac, I am a bit unsure what to
>>>> make of all that. Is Mac OSX
>>>> a second-class citizen as far as dev resources are concerned?
>>>>
>>>> Tobi and Chris, have you filed Jira Issues on Mac graphics
>>>> performance that can be tracked?
>>>>
>>>> I will file an issue with a simple test case and hope for the best.
>>>>
>>>>
>>>>
>>>>
>>>>
>>>>
>>>> On Fri, Mar 27, 2015 at 11:08 PM, Chris Newland
>>>> <cnewland at chrisnewland.com>
>>>> wrote:
>>>>
>>>>
>>>>
>>>>> Possibly related:
>>>>>
>>>>>
>>>>>
>>>>> I can reproduce a massive (90%) performance drop on OSX between
>>>>> drawing a wireframe polygon on a Canvas using a series of
>>>>> gc.strokeLine(double x1, double y1, double x2, double y2) commands
>>>>> versus using a single gc.strokePolygon(double[] xPoints, double[]
>>>>> yPoints, int count) command.
>>>>>
>>>>> Creating the polygons manually with strokeLine() is significantly
>>>>> faster using the ES2Pipeline on OSX.
>>>>>
>>>>> This is reproducible in a little GitHub JavaFX benchmarking project
>>>>>   I've
>>>>> created: https://github.com/chriswhocodes/DemoFX
>>>>>
>>>>>
>>>>>
>>>>> Build with ant
>>>>>
>>>>>
>>>>>
>>>>> Run with:
>>>>>
>>>>>
>>>>>
>>>>> # use strokeLine
>>>>> ./run.sh -c 5000 -m line
>>>>> result: 60 (sixty) fps
>>>>>
>>>>>
>>>>>
>>>>> # use strokePolygon
>>>>> ./run.sh -c 5000 -m poly
>>>>> result: 6 (six) fps
>>>>>
>>>>>
>>>>>
>>>>> System is 2011 iMac 27" / Mavericks / 3.4GHz Core i7 / 20GB RAM /
>>>>> Radeon
>>>>> 6970M 1024MB
>>>>>
>>>>>
>>>>>
>>>>> Looking at the code paths in javafx.scene.canvas.GraphicsContext:
>>>>>
>>>>>
>>>>>
>>>>> gc.strokeLine() maps to writeOp4(x1, y1, x2, y2,
>>>>> NGCanvas.STROKE_LINE)
>>>>>
>>>>>
>>>>> gc.strokePolygon() maps to writePoly(xPoints, yPoints, nPoints,
>>>>> true, NGCanvas.STROKE_PATH) which involves significantly more work
>>>>> with adding to and flushing a GrowableDataBuffer.
>>>>>
>>>>> I've not had time to dig any deeper than this but it's surely a bug
>>>>>   when building a poly manually is 10x faster than using the
>>>>> convenience method.
>>>>>
>>>>> Cheers,
>>>>>
>>>>>
>>>>>
>>>>> Chris
>>>>>
>>>>>
>>>>>
>>>>> On Fri, March 27, 2015 21:26, Tobias Bley wrote:
>>>>>
>>>>>
>>>>>> In my opinion the whole graphics performance on MacOSX
>>>>>> isn’t good at all with JavaFX….
>>>>>>
>>>>>>
>>>>>>> Am 27.03.2015 um 22:10 schrieb Robert Krüger
>>>>>>> <krueger at lesspain.de>:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> The bad full screen performance is without the arcs. It is just
>>>>>>> one call to fillRect, two to strokeOval and one to fillOval,
>>>>>>> that's all. I will build a simple test case and file an issue.
>>>>>>>
>>>>>>> On Fri, Mar 27, 2015 at 9:58 PM, Jim Graham
>>>>>>> <james.graham at oracle.com>
>>>>>>> wrote:
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>> Hi Robert,
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> Please file a Jira issue with a simple test case.  Arcs are
>>>>>>>> handled as a generalized shape rather than via a predetermined
>>>>>>>>   shader, but it shouldn't be that slow.  Something else may
>>>>>>>> be going on.
>>>>>>>>
>>>>>>>> Another test might be to replace the arcs with rectangles or
>>>>>>>> ellipses and see if the performance changes...
>>>>>>>>
>>>>>>>> ...jim
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> On 3/27/15 1:52 PM, Robert Krüger wrote:
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>>> Hi,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> I have a super-simple animation implemented using
>>>>>>>>> AnimationTimer
>>>>>>>>> and Canvas where the canvas just performs a few draw
>>>>>>>>> operations, i.e. fills the screen with a color and then
>>>>>>>>> draws and fills 2-3 circles and I have already observed that
>>>>>>>>> each drawing operation I add, results in
>>>>>>>>> significant CPU load (e.g. when I draw < 10 arcs in addition
>>>>>>>>> to the circles, the CPU load goes up to 30-40% on a Mac Book
>>>>>>>>> Pro
>>>>>>>>> for a Canvas size of 600x600(!).
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Now I tested the animation in full screen mode (only with a
>>>>>>>>> few circles) and playback is unusable for a serious
>>>>>>>>> application (very
>>>>>>>>> choppy). Is 2D canvas performance known to be very bad on
>>>>>>>>> Mac or
>>>>>>>>> am I doing something wrong? Are there workarounds for this?
>>>>>>>>>
>>>>>>>>> Thanks,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Robert
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>>>
>>>>>>>
>>>>>>> --
>>>>>>> Robert Krüger
>>>>>>> Managing Partner
>>>>>>> Lesspain GmbH & Co. KG
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> www.lesspain-software.com
>>>>>>
>>>>>
>>>>>
>>>>
>>>> --
>>>> Robert Krüger
>>>> Managing Partner
>>>> Lesspain GmbH & Co. KG
>>>>
>>>>
>>>>
>>>> www.lesspain-software.com
>>>>
>>>
>



More information about the openjfx-dev mailing list