chunky-dev / chunky-dev/chunky

New NullPointerExceptions caused by large canvas sizes?

Open
#1,081 1 comment 0 reactions 0 assignees View on GitHub
Dominant language
Java
Stars
738
Forks
78
Avg merge
10h 5m
Merged PRs (30d)
3

Description

JavaFX hardware acceleration has a maximum supported texture size defined within the graphics driver. In the past it was possible to disable hardware acceleration and use software rendering using `-Dprism.order=sw` which shifts the majority of limits towards the sample buffer which has a 12800x12800 upper limit if memory allows. See PR https://github.com/chunky-dev/chunky/pull/786 for all related issues as well various fixes.

Typically this crops up as:

```
java.lang.NullPointerException
at com.sun.prism.d3d.D3DTexture.getContext(D3DTexture.java:84)
at com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:207)
at com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:151)
at com.sun.prism.impl.BaseContext.flushMask(BaseContext.java:112)
at com.sun.prism.impl.BaseContext.drawQuads(BaseContext.java:121)
at com.sun.prism.impl.VertexBuffer.flush(VertexBuffer.java:98)
at com.sun.prism.impl.BaseContext.flushVertexBuffer(BaseContext.java:104)
at com.sun.prism.impl.ps.BaseShaderContext.setRenderTarget(BaseShaderContext.java:753)
at com.sun.prism.impl.BaseContext.setRenderTarget(BaseContext.java:146)
at com.sun.prism.impl.BaseGraphics.(BaseGraphics.java:106)
at com.sun.prism.impl.ps.BaseShaderGraphics.(BaseShaderGraphics.java:86)
at com.sun.prism.d3d.D3DGraphics.(D3DGraphics.java:42)
at com.sun.prism.d3d.D3DGraphics.create(D3DGraphics.java:65)
at com.sun.prism.d3d.D3DSwapChain.createGraphics(D3DSwapChain.java:131)
at com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:87)
at java.util.concurrent.Executors$RunnableAdapter.call(Unknown Source)
at java.util.concurrent.FutureTask.runAndReset(Unknown Source)
at com.sun.javafx.tk.RenderJob.run(RenderJob.java:58)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
at com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:125)
at java.lang.Thread.run(Unknown Source)
```

Or in cases where memory runs out before you reach the maximum supported texture size or the sample buffer maximum:

```
java.lang.OutOfMemoryError: Java heap space
at javafx.graphics/com.sun.prism.sw.SWArgbPreTexture.allocateBuffer(SWArgbPreTexture.java:182)
at javafx.graphics/com.sun.prism.sw.SWTexture.allocate(SWTexture.java:272)
at javafx.graphics/com.sun.prism.sw.SWRTTexture.(SWRTTexture.java:50)
at javafx.graphics/com.sun.prism.sw.SWResourceFactory.createRTTexture(SWResourceFactory.java:135)
at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas$RenderBuf.validate(NGCanvas.java:212)
at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.initCanvas(NGCanvas.java:644)
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.sg.prism.NGGroup.renderContent(NGGroup.java:270)
at javafx.graphics/com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
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.sg.prism.NGGroup.renderContent(NGGroup.java:270)
at javafx.graphics/com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
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.sg.prism.NGGroup.renderContent(NGGroup.java:270)
at javafx.graphics/com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.renderForClip(NGNode.java:2313)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.renderRectClip(NGNode.java:2207)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.renderClip(NGNode.java:2233)
at javafx.graphics/com.sun.javafx.sg.prism.CacheFilter.renderNodeToCache(CacheFilter.java:683)
at javafx.graphics/com.sun.javafx.sg.prism.CacheFilter.render(CacheFilter.java:587)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.renderCached(NGNode.java:2377)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.doRender(NGNode.java:2063)
at javafx.graphics/com.sun.javafx.sg.prism.NGNode.render(NGNode.java:1964)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderContent(NGGroup.java:270)
at javafx.graphics/com.sun.javafx.sg.prism.NGRegion.renderContent(NGRegion.java:579)
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.sg.prism.NGGroup.renderContent(NGGroup.java:270)

```

However in more recent testing with both Temurin-17.0.1+12 & OpenJFX 17.0.1, on Windows 10 Home 21H1 (build 19043.1348), and Java 8 update 311, on Windows 7 Pro version 6.1 (build 7601: SP1), a different set of NullPointerExceptions can be noted on both `d3d`/`hw` and `sw` pipelines. This testing extends to both Chunky 2.3.0 and 2.4.1. Important to note that this is **NOT** a regression with Chunky but something unexplainable is occurring. In the past with Chunky 2.3.0 it was possible to render at up to 12800x12800 without unexplained issues on my system with around 10,000 chunks loaded. For whatever reason both my system and that of another user are facing issues where they did not exist before.

`sw` & `d3d`/`hw`
```
java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null
at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas$RenderBuf.validate(NGCanvas.java:214)
at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.initCanvas(NGCanvas.java:644)
at javafx.graphics/com.sun.javafx.sg.prism.NGCanvas.renderForcedContent(NGCanvas.java:628)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.sg.prism.NGGroup.renderForcedContent(NGGroup.java:232)
at javafx.graphics/com.sun.javafx.tk.quantum.ViewPainter.paintImpl(ViewPainter.java:331)
at javafx.graphics/com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:92)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
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:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:126)
at java.base/java.lang.Thread.run(Thread.java:833)
```

`d3d`/`hw`
```
java.lang.NullPointerException: Cannot invoke "com.sun.prism.d3d.D3DTextureData.getContext()" because the return value of "com.sun.prism.d3d.D3DTextureResource.getResource()" is null
at javafx.graphics/com.sun.prism.d3d.D3DTexture.getContext(D3DTexture.java:85)
at javafx.graphics/com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:210)
at javafx.graphics/com.sun.prism.d3d.D3DTexture.update(D3DTexture.java:154)
at javafx.graphics/com.sun.prism.impl.BaseContext.flushMask(BaseContext.java:115)
at javafx.graphics/com.sun.prism.impl.BaseContext.drawQuads(BaseContext.java:124)
at javafx.graphics/com.sun.prism.impl.VertexBuffer.flush(VertexBuffer.java:98)
at javafx.graphics/com.sun.prism.impl.BaseContext.flushVertexBuffer(BaseContext.java:107)
at javafx.graphics/com.sun.prism.impl.ps.BaseShaderContext.setRenderTarget(BaseShaderContext.java:789)
at javafx.graphics/com.sun.prism.impl.BaseContext.setRenderTarget(BaseContext.java:149)
at javafx.graphics/com.sun.prism.impl.BaseGraphics.(BaseGraphics.java:107)
at javafx.graphics/com.sun.prism.impl.ps.BaseShaderGraphics.(BaseShaderGraphics.java:86)
at javafx.graphics/com.sun.prism.d3d.D3DGraphics.(D3DGraphics.java:42)
at javafx.graphics/com.sun.prism.d3d.D3DGraphics.create(D3DGraphics.java:65)
at javafx.graphics/com.sun.prism.d3d.D3DSwapChain.createGraphics(D3DSwapChain.java:148)
at javafx.graphics/com.sun.javafx.tk.quantum.PresentingPainter.run(PresentingPainter.java:88)
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:539)
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:1136)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635)
at javafx.graphics/com.sun.javafx.tk.quantum.QuantumRenderer$PipelineRunnable.run(QuantumRenderer.java:126)
at java.base/java.lang.Thread.run(Thread.java:833)
```

---

Tested using `-Dprism.verbose=true` to get pipeline information. Using `-Dprism.order` to switch render pipeline (`sw`, `d3d`/`hw`). Also tried using `-Dprism.maxvram` with either render pipeline.

`d3d`/`hw` (hardware accelerated pipeline) gives the following readout with my RTX 2070 (Win10).

```
Initialized prism pipeline: com.sun.prism.d3d.D3DPipeline
Maximum supported texture size: 16384
Maximum texture size clamped to 4096
```

---

`sw` (software pipeline):

- 5000 x 5000 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@5a6cab0b target to 400,000,000`
- 5500 x 5500 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@346aedef target to 484,000,000`
- 6000 x 6000 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`
- 8192 x 8192 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`

Using `-Dprism.maxvram=8G`

- 8192 x 8192 - Working preview - n/a
- 9000 x 9000 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@3591efe2 target to 1,296,000,000`
- 10000 x 10000 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@3591efe2 target to 1,600,000,000`
- 12800 x 12800 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@3591efe2 target to 2,621,440,000`
- 12801 x 12801 - Working preview - `Growing pool com.sun.prism.sw.SWTexturePool@3591efe2 target to 2,621,849,616`
- 16384 x 16384 - Breaks as expected - `java.lang.IllegalArgumentException: WIDTH * HEIGHT is too large`

---

`d3d`/`hw` (hardware accelerated pipeline):

- 4096 x 4096 - Working preview - `Growing pool D3D Vram Pool target to 406,489,550`
- 4097 x 4097 - Working preview - `Growing pool D3D Vram Pool target to 412,357,517`
- 5000 x 5000 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.d3d.D3DTextureData.getContext()" because the return value of "com.sun.prism.d3d.D3DTextureResource.getResource()" is null`

Using `-Dprism.maxvram=8G`

- 5000 x 5000 - Working preview - n/a
- 6000 x 6000 - Working preview - `Growing pool D3D Vram Pool target to 1,119,668,111`
- 7000 x 7000 - Working preview - `Growing pool D3D Vram Pool target to 1,547,668,111`
- 8192 x 8192 - Working preview - `Growing pool D3D Vram Pool target to 2,097,412,321`
- 9000 x 9000 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`
- 10000 x 10000 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`
- 12800 x 12800 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`
- 16384 x 16384 - Broken UI - `java.lang.NullPointerException: Cannot invoke "com.sun.prism.d3d.D3DTextureData.getContext()" because the return value of "com.sun.prism.d3d.D3DTextureResource.getResource()" is null` / `java.lang.NullPointerException: Cannot invoke "com.sun.prism.RTTexture.createGraphics()" because "" is null`

---

From the data that I have collected using `-Dprism.maxvram` to assign more memory seems to mitigate these new NullPointerExceptions however the key question is how did theses new Exceptions arrise on both Chunky 2.4.X and 2.3.0 on two different systems with different Java setups.

Contributor guide

Open the contributing guide

Research direction

Start by reproducing the reported JavaFX failures across the `sw` and `d3d`/`hw` pipelines using `-Dprism.verbose=true`, `-Dprism.order`, and `-Dprism.maxvram`. Review the cited JavaFX stack traces, PR #786, and the documented canvas-size results; done requires identifying a Chunky-side change or a confirmed external JavaFX/driver cause.

Written by the indexing model from the issue text.

Assessment

Tech stack
java
Domain
computer-graphics, desktop
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
20/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.