JDK-8125958 : With accelerated compositing, WebView starts dumping NPEs on http://neography.com/experiment/circles/solarsystem
Type:Bug
Component:javafx
Sub-Component:web
Affected Version:8
Priority:P3
Status:Resolved
Resolution:Fixed
Submitted:2012-09-05
Updated:2015-06-17
Resolved:2013-11-14
The Version table provides details related to the release that this issue/RFE will be addressed.
Unresolved : Release in which this issue/RFE will be addressed. Resolved: Release in which this issue/RFE has been resolved. Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.
After RT-22913 is implemented, WebView starts dumping NPEs on http://neography.com/experiment/circles/solarsystem
Comments
If you are asking how you find out programmatically if textures are reclaimed, you use the Texture.isSurfaceLost() method and it tells you if your texture was disposed by someone. On D3D it will also tell you if the system has catastrophically deleted all textures due to another app going full screen exclusive so your code is not correct until it checks this method regardless of any makePermanent or other settings (that type of surface loss is completely out of our control).
29-11-2013
java -Dprism.poolstats=true will give you some statistics. I don't know off hand if there is other logging mechanisms.
29-11-2013
At least for Saturn rings the plane requested is 10k x 10k. I'm not sure how much is requested for planets but they must be multi-tile, too.
How can I get notifications about textures being reclaimed?
28-11-2013
Why are the planet textures 2k x 2k? Is the HTML code actually requesting that much space somehow?
27-11-2013
If the layers can be rerendered if need be, then they should be marked contentsUseful() and unlocked() as soon as you are done using them. They must be unlocked by the end of a rendering cycle, but the lock() should be limited in scope as much as feasible. The ManagedResource mechanism will prioritize them based on keeping useful textures around longer than those not marked useful, and also by age (in terms of how recently they were locked).
markPermanent() is only meant for textures for which there is absolutely no way to recover the pixels.
27-11-2013
The idea of accelerated compositing as implemented in Webkit is to break the scene being animated into layers, render each layer once, then at each animation step update the layers' positions relative to each other, and compose the layers. So steps 1-5 are performed rarely. Once the layer is rendered its lifetime can be very long -- in this particular demo, infinite, as no updates ever occur to the planets -- so the layers are permanent by nature.
Fixed is the maximum tile size only, so that if a layer exceeds that size it is broken into tiles, e.g. a 2100x100 layer will produce two tiles, one 2048x100 and the other one 52x100. No space is wasted here on the first glance. In this test however, one 10k x 10k layer will produce 25 tiles of which at most 4 will be actually used to render a planet, and at least 21 will forever remain empty.
The idea of the patch was to postpone creating textures for RTImages until some "real" rendering was requested. So steps 1-3 wouldn't cause the texture to be created, and if nothing was rendered at step 4, we'd have an RTImage with no texture at all. This might be a reasonable change, even though it makes code more complex.
Unfortunately that doesn't push memory consumption below the limit. For each planet at least one 2048x2048 texture is created and they use up too much space. For this particular test a much smaller maximum tile size would work, e.g. with 256x256 tiles the amount of memory occupied by planets' layers would be 64 times less in the best case, and that could "fix" the issue. However this is a change I'd like to avoid.
27-11-2013
It's hard for me to translate those steps into the code I see. Also, if the steps 1-5 are always done, then isn't the tile just a temporary buffer that doesn't need its contents saved from one frame to the next? If a tile is always cleared at the start of an operation, can't the texture be locked in step 1 and unlocked in step 5? That way they don't interfere with allocations.
Also, why are the tile sizes fixed? Shouldn't they be based on the size of the layers being composited? There was at least one method that took a set of dxy12 parameters from which it looks like you could infer the necessary size and reallocate if needed so the textures grow based on usage.
Another observation - if these objects are hanging on to temporary buffers, shouldn't they be using a pool system to share their temp buffers? I haven't yet created a temp buffer pool in prism, but I plan to eventually. Meanwhile, the Effect package has a pool that some parts of the system are using, but it involves a number of wrappers that can be cumbersome for non-decora code.
26-11-2013
Filed RT-34289.
Cannot close this as verified.
14-11-2013
Alexander: Please file a new issue and link it to this one. A bug that is marked as "Fixed" as the result of a changeset pushed to the repo should not be reopened for a partial or complete fix failure (unless that changeset was backed out).
14-11-2013
Some time after the initial issue has been fixed, a limit on the total amount of memory occupied by textures has been implemented in Prism. With this particular test WebView hits this limit, hence the exception.
This test creates very large layers (about 10K x 10K for the Saturn ring). Because they are so large, Webkit breaks them into tiles with maximum size of 2048. Only few of those tiles are actually used, but we create textures for all the tiles, quickly eating up all the memory available for textures.
For each tile, Webkit runs the following routine:
1) clear the tile
2) save context state
3) set clip and translation
4) render part of the layer
5) restore context state
We need a graphics context at step 1 to clear the tile, so we create a texture. Thus we have textures even for empty tiles (those for which the layer paints nothing at step 4). This can be fixed by skipping the clear operation if the texture does not exist, plus some other changes to make sure no texture is created until really needed.
When this is fixed, we still use too much memory because tiles are too big, e.g. one tiny planet can take a 2048x2048 tile. To fix this we can decrease maximum tile size. 512 works for me -- the number of tiles goes up, but their size down, and overall it is a win.
Attached is a patch (rt.patch) that implements both ideas. I do not feel like pushing it however. It adds complexity, and choice of tile size seems an ad hoc fine tuning aimed at this particular test. As the use case is not important, and rare, I'd like not to apply this fix.
02-10-2013
I see exception :
java.lang.NullPointerException
at com.sun.javafx.webkit.prism.WCGraphicsPrismContext$ClipLayer.render(WCGraphicsPrismContext.java:1251)
at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.renderLayer(WCGraphicsPrismContext.java:158)
at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.restoreStateInternal(WCGraphicsPrismContext.java:176)
at com.sun.javafx.webkit.prism.WCGraphicsPrismContext.restoreState(WCGraphicsPrismContext.java:189)
at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:202)
at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:69)
at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:80)
at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:86)
at com.sun.webkit.graphics.GraphicsDecoder.decode(GraphicsDecoder.java:322)
at com.sun.webkit.graphics.WCRenderQueue.decode(WCRenderQueue.java:69)
at com.sun.webkit.WebPage.paint2GC(WebPage.java:669)
at com.sun.webkit.WebPage.paint(WebPage.java:637)
at com.sun.javafx.sg.prism.NGWebView.renderContent(NGWebView.java:73)
at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2028)
at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1937)
at com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:225)
at com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:1168)
at com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2028)
at com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1937)
at com.sun.javafx.tk.quantum.ViewPainter.doPaint(ViewPainter.java:472)
at com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:324)
at com.sun.javafx.tk.quantum.UploadingPainter.run(UploadingPainter.java:113)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308)
at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:129)
at java.lang.Thread.run(Thread.java:724)
I pressed on solar system several times using LMB, and didn't smth like DnD gesture on the solar system.
06-09-2013
The above fix has been pushed as http://jfxsrc.us.oracle.com/javafx/8.0/scrum/graphics/webnode/rev/c2758a536389
13-09-2012
Here is the fix.
Webrev: http://javaweb.us.oracle.com/jcg/fx-webrevs/RT-24738/1
Summary of changes:
- In TextureMapperLayer::updateBackingStore(), instead of creating a huge intermediate ImageBuffer and painting the layer into it, paint the layer directly into each individual backing store tile.
Note that all the changes are in shared texture mapper code. If you see a better alternative, please do not hesitate to point it out.