I have been struggling with an “interesting” javafx render problem. In BpmDj, given enough updates, the rendertree would partially stop updating. It was clear this was a concurrency bug, yet one that was not my fault. As a preliminary solution to fix this I would grab a screenshot everytime I would add a node. Recently however that solution no longer worked and the dirty logic would be so fucked up that elements which should be visible were not visible. It was even possible to have a font change its color halfway through its rendering.
So I started to look around for javafx options, and there are a few of them that proved to be useful.
What | Flag | Default |
---|---|---|
VSync | prism.vsync | true |
Dirty region optimizations | prism.dirtyopts | true |
Occlusion Culling | prism.occlusion.culling | true |
dirtyRegionCount | prism.dirtyregioncount | 15 |
Scrolling cache optimization | prism.scrollcacheopt | false |
Dirty region optimizations | prism.threadcheck | false |
Draws overlay rectangles showing where the dirty regions were | prism.showdirty | false |
Draws overlay rectangles showing not only the dirty regions, but how many times each area within that dirty region was drawn (covered by bounds of a drawn object). | prism.showoverdraw | false |
Prints out the render graph, annotated with dirty opts information | prism.printrendergraph | false |
Force scene repaint on every frame | prism.forcerepaint | false |
disable fallback to another toolkit if prism couldn’t be init-ed | prism.noFallback | false |
Shape caching optimizations | prism.cacheshapes | complex |
New javafx-iio image loader | prism.newiio | true |
Verbose output | prism.verbose | false |
Prism statistics print frequency, <=0 means “do not print” | prism.printStats | 0 |
Debug output | prism.debug | false |
Trace output | prism.trace | false |
Print texture allocation data | prism.printallocs” | false |
Disable bad driver check warning | prism.disableBadDriverWarning” | false |
Force GPU, if GPU is PS 3 capable, disable GPU qualification check. | prism.forceGPU | false |
Skip mesh normal computation | prism.experimental.skipMeshNormalComputation | false |
Which driver to use | prism.order | |
prism.forcepowerof2 | false | |
prism.noclamptozero | false | |
Try -Dprism.maxvram=[kKmMgG] | prism.allowhidpi | true |
prism.maxvram | 512 * 1024 * 1024 | |
Try -Dprism.targetvram=[kKmMgG]|<double(0,100)>% | prism.targetvram | |
prism.poolstats | false | |
prism.pooldebug | false | |
prism.maxTextureSize | ||
prism.minrttsize | ||
prism.disableRegionCaching | ||
prism.disableD3D9Ex | false | |
prism.disableEffects | false | |
prism.glyphCacheWidth | 1024 | |
prism.glyphCacheHeight | 1024 | |
Enable the performance logger, print on exit, print on first paint etc. | sun.perflog | |
sun.perflog.fx.exitflush | ||
sun.perflog.fx.firstpaintflush | ||
sun.perflog.fx.firstpaintexit | ||
prism.supershader | true | |
Force uploading painter (e.g., to avoid Linux live-resize jittering) | prism.forceUploadingPainter | false |
Force the use of fragment shader that does alpha testing (i.e. discard if alpha == 0.0) | prism.forceAlphaTestShader | false |
Force non anti-aliasing (not smooth) shape rendering | prism.forceNonAntialiasedShape | false |
Set Single GUI Threading | quantum.singlethreaded | false |
Print quantum verbose | quantum.verbose | false |
JavaFx framerate in FPS | javafx.animation.pulse | 60 |
FX thread collision with Render thread ?
When running with the prism.threadcheck option I got the following error:
ERROR: PrismPen / FX threads co-running: DIRTY: false FX: java.lang.Thread.getStackTrace(Thread.java:1559) FX: com.sun.javafx.tk.quantum.QuantumRenderer.checkRendererIdle(QuantumRenderer.java:247) FX: com.sun.javafx.tk.quantum.QuantumToolkit.checkFxUserThread(QuantumToolkit.java:424) FX: javafx.scene.Scene$MouseHandler.process(Scene.java:3680) FX: javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485) FX: javafx.scene.Scene$MouseHandler$1.run(Scene.java:3521) FX: com.sun.javafx.application.PlatformImpl.lambda$null$173(PlatformImpl.java:295) FX: java.security.AccessController.doPrivileged(Native Method) FX: com.sun.javafx.application.PlatformImpl.lambda$runLater$174(PlatformImpl.java:294) FX: com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95) FX: com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method) FX: com.sun.glass.ui.gtk.GtkApplication.lambda$null$49(GtkApplication.java:139) FX: java.lang.Thread.run(Thread.java:748) QR: com.sun.javafx.sg.prism.NGCanvas.getStroke(NGCanvas.java:777) QR: com.sun.javafx.sg.prism.NGCanvas.setupStroke(NGCanvas.java:785) QR: com.sun.javafx.sg.prism.NGCanvas.handleRenderOp(NGCanvas.java:1212) QR: com.sun.javafx.sg.prism.NGCanvas.renderStream(NGCanvas.java:1097) QR: com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:606) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) QR: com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) QR: com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) QR: com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) QR: com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:235) QR: com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:576) QR: com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2053) QR: com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1945) QR: com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:477) QR: com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:330) QR: com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:91) QR: java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) QR: java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) QR: com.sun.javafx.tk.RenderJob.run(RenderJob.java:58) QR: java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) QR: java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) QR: com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125) QR: java.lang.Thread.run(Thread.java:748)
Of course how that related to my problem wasn’t clear, allthough maybe it could explain why the dirty flags were all ****ed up.
Overdraw and dirty draws
The option -Dprism.showoverdraw=true is interesting because it shows us which area we drew once (red), which twice (green), and so on. This showed me that the areas that didn’t update were not even marked as ‘dirty’. Suggesting that the problem was indeed with the setting and tracking of the dirty flag in the renderer. Therefore we tried the option -Dprism.dirtyopts=false and hooray all problems disappeared. Of course the app ran slightly slower, but at least it worked now.
Thank you, your post is very helpful!
Is there any command that improves the frame rate in JavaFX?
javafx.animation.pulse sets the framerate. But normally it is already 60fps. So if it still lags it is probably a driver issue or some other thing that stalls the pipeline.
You have a typo:
“Therefore we tried the option -Dprism.dirtopts=false ”
You have missed the y from dirty
And this cured my problem where menus were leaving the background box behind them after repeated use of our system for a week or so !
Yeah, I spent a small month figuring this out. Seriously.
Hmmm – it appeared to but didn’t !
I would ask: does the -Dprism.showoverdraw=true actually color rectangles ? If so, then you know how to set the -Dprism.dirtyopts=false If not, then maybe you weren’t able to set the flag properly ?
In my case the rendering problems finally turned out to be caused by a single missing Platform.runLater(…) around some calls to TextField.setText(…) (called from another thread than the JFX UI thread). After this was fixed everything worked fine. Maybe it’s also the solution for others…