B4J Question Canvas Snapshot Crash

RobertK

Member
Licensed User
To follow up on

Sorry I have been away longer than expected.

Regarding your question about whether Fast3D is open source, Erel, I first need to sort out some outstanding issues. Foremost among these is the Canvas Snapshot crash first reported in https://www.b4x.com/android/forum/threads/canvas-snapshot-size-limit.127859/

The maximum size of the canvas is now kept well below the upper limit, however Snapshot still crashes erratically with the following java.lang.NullPointerException:

Error message:
java.lang.NullPointerException
    at javafx.graphics/com.sun.prism.d3d.D3DTexture.getContext(D3DTexture.java:84)
    at javafx.graphics/com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:207)
    at javafx.graphics/com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:151)
    at javafx.graphics/com.sun.prism.impl.BaseContext.flushMask(BaseContext.java:109)
    at javafx.graphics/com.sun.prism.impl.BaseContext.drawQuads(BaseContext.java:118)
    at javafx.graphics/com.sun.prism.impl.VertexBuffer.flush(VertexBuffer.java:98)
    at javafx.graphics/com.sun.prism.impl.BaseContext.flushVertexBuffer(BaseContext.java:101)
    at javafx.graphics/com.sun.prism.impl.ps.BaseShaderContext.setRenderTarget(BaseShaderContext.java:746)
    at javafx.graphics/com.sun.prism.impl.BaseContext.setRenderTarget(BaseContext.java:131)
    at javafx.graphics/com.sun.prism.impl.BaseGraphics.<init>(BaseGraphics.java:106)
    at javafx.graphics/com.sun.prism.impl.ps.BaseShaderGraphics.<init>(BaseShaderGraphics.java:86)
    at javafx.graphics/com.sun.prism.d3d.D3DGraphics.<init>(D3DGraphics.java:42)
    at javafx.graphics/com.sun.prism.d3d.D3DGraphics.create(D3DGraphics.java:65)
    at javafx.graphics/com.sun.prism.d3d.D3DRTTexture.createGraphics(D3DRTTexture.java:77)
    at javafx.graphics/com.sun.prism.d3d.D3DResourceFactory.createRTTexture(D3DResourceFactory.java:316)
    at javafx.graphics/com.sun.prism.d3d.D3DResourceFactory.createRTTexture(D3DResourceFactory.java:270)
    at javafx.graphics/com.sun.prism.d3d.D3DResourceFactory.createRTTexture(D3DResourceFactory.java:63)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSDrawable.create(PPSDrawable.java:59)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSRenderer.createCompatibleImage(PPSRenderer.java:163)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSRenderer.createCompatibleImage(PPSRenderer.java:67)
    at javafx.graphics/com.sun.scenario.effect.impl.ImagePool.checkOut(ImagePool.java:183)
    at javafx.graphics/com.sun.scenario.effect.impl.Renderer.getCompatibleImage(Renderer.java:116)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSRenderer.getCompatibleImage(PPSRenderer.java:168)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSTwoSamplerPeer.filterImpl(PPSTwoSamplerPeer.java:62)
    at javafx.graphics/com.sun.scenario.effect.impl.prism.ps.PPSEffectPeer.filter(PPSEffectPeer.java:54)
    at javafx.graphics/com.sun.scenario.effect.CoreEffect.filterImageDatas(CoreEffect.java:106)
    at javafx.graphics/com.sun.scenario.effect.Blend.filterImageDatas(Blend.java:37)
    at javafx.graphics/com.sun.scenario.effect.FilterEffect.filter(FilterEffect.java:195)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.applyEffectOnAintoC(NGCanvas.java:738)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.blendAthruBintoC(NGCanvas.java:768)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.renderClip(NGCanvas.java:724)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.initClip(NGCanvas.java:711)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.renderStream(NGCanvas.java:1056)
    at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.renderContent(NGCanvas.java:607)
    at javafx.graphics/com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2072)
    at javafx.graphics/com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit$5.draw(QuantumToolkit.java:1411)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumToolkit$5.run(QuantumToolkit.java:1447)
    at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515)
    at java.base/java.util.concurrent.FutureTask.runAndReset(FutureTask.java:305)
    at javafx.graphics/com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
    at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
    at java.base/java.lang.Thread.run(Thread.java:834)

This would appear to correspond to a OpenJDK bug reported here

Can anyone suggest workarounds?

Many thanks!
 

RobertK

Member
Licensed User
Thanks for your quick reply, Erel.

No, the error does not crash the app right away, but once the error has occurred all subsequent calls to Canvas.Shapshot throw the same error, as described in the JDK Bug Report:

“After this moment, every GUI rendering causes a NullPointerException (triggered by the method BaseContext.flushMask()), meaning an endless loop causing a GUI freeze.”

After 129 times, the app crashes.

Finding exactly what triggers the error is not easy. The Canvas.Shapshot statement is inside nested loops and is executed very frequently. Sometimes it throws the error almost immediately, at other times only after hundreds of thousands of calls. It does not seem to depend on the canvas size nor the number of vertices in the clipping polygon applied to the canvas using ClipPath. My code does trap the error when it occurs but is unable to resume its calculations because Canvas.Shapshot has stopped working.

As a temporary patch, I have implemented a monitor app which runs as an independent process. When the main app traps the error it raises a flag (in a file) before terminating. The monitor app detects the flag and restarts the main app which continues its calculations where it left off. This works but is not a satisfactory long term solution.

I have also tried or considered the following:

1) Allocating additional memory using -Xmx10G
It does not help.

Would using -Dprism.maxvram=10G be more effective?
But this is still not a satisfactory long term solution, crashes would eventually occur when processing large datasets.

2) Forcing garbage collection at regular intervals as outlined here
It does not help.

Is there a way to force the specific cleanup referred to in the JDK Bug Report?

“If the BaseResourcePool runs out of available space (maxSize is reached), it performs a cleanup to remove dead/unused textures and free some space.”

3) Do you think that switching from Open JDK 11 to Oracle Java 8 might help?

Any other ideas?

Thanks.
 
Upvote 0

RobertK

Member
Licensed User
Thanks for your latest suggestions, Erel.

Unfortunately Open JDK 14 does not help, it has the same bug. I have not yet tried Oracle Java 8.

In the meantime, allocating additional memory with -Dprism.maxvram allows me to process large datasets. Perhaps this can tide me over until they fix the bug. Or am I being too optimistic? The original bug report is dated 2017, last updated 2018. How long do such fixes usually take?
 
Upvote 0
Top