P2D Renderer slows sketch down to extreme framerate

I have been writing a Processing application/sketch in Eclipse (due to external libraries and heavy OOP) and stumbled upon this problem:

During the drawing process (initialized from a normal draw() method in my PApplet subclass) I am delegating some functionality to a second class, which creates PGraphics and does some rendering on them:

PGraphics buffer = master.createGraphics(master.width, master.height, PConstants.P2D);
buffer.beginDraw();
renderPage(page, buffer); //does some rendering on the buffer including draw calls, push/pop operations & translations, fill, stroke etc.
buffer.endDraw();

(master is my PApplet subclass responsible for the screen)
The buffer is then drawn to the screen, sometimes with resizing.

The issue is the following: making the sketch use the “P2D” renderer (and the graphics buffer, as seen above) lowers the framerate to around 0.05-0.1 (one frame per 10-20 seconds). frameRate(60) has absolutely no effect.

I have stepped through the code with the debugger and there is some semi-random behavior: at least one of the functions executing a draw call (such as text() or background()) take the observed 10-20 seconds to execute. This also occurs sometimes inside the beginDraw() implementation of PGraphics2D (or PGraphicsOpenGL) where certain methods take a lot of time. After such a method was executed, all the rest of the frame is finished in no time at all (stepping is always finished before any noticeable slowdown).

It really depends on where I put the breakpoints, and time measurement with System.currentTimeMillis() only measures up to 20ms for even the heaviest draw methods, so I am very sure the issue is not in these self-written methods.

Funny thing is: When I change all renderers to JAVA2D, my program runs at full 60fps with no slowdown whatsoever. Luckily, the application does not require P2D, so I will stick with the default renderer for now.

My point is: Am I doing something wrong or is Eclipse or the JRE not liking the P2D?

I have included Processing 3.3.6 as a User Library, with referenced source folders (this is working correctly). I have added the core.jar as well as gluegen-rt.jar and jogl-all.jar. For both the /core/library directory is referenced as the Native Library Location. Using the special native JAR’s for my architecture (Windows 10 x64 (64 bit) so the natives-windows-i586 jars) directly in both cases leads to NoClassDefFoundException's etc.

Both Java 10.0.1 and Java 1.8 have the same exact issue, although there is a reflect warning thrown for Java 10 from the JOGL library (probably has to do with compliance etc. but again, Java 1.8 does not solve the issue).

Thanks in advance!

kleinesfilmröllchen

1 Like

One thing I’m thinking about right now is, if it’s Processing’s functions(i.e. text() or background()) that take so much time, what if you were to, instead of using the .jar files, used straight up Processing source code, and find the exact function call inside of text() that causes the long slowdown - and then find that function’s source code too, and find what part of it creates the long wait, and so on…

Also, what if you createGraphics the buffer with JAVA2D renderer, but use P2D for the whole sketch?

As I said it is pretty random and dependent on where the breakpoints are where to find a slowdown.

I have been stepping into the source code (source was attached all the time but the code is executed from the jar, you know how that works) and found indeterminate behavior there too, so sometimes the cause were some OpenGL functions, sometimes some Processing functions. I have not been stepping into the several layers of libraries, I figured it was not worth the effort. If no solution proves to be useful I might consider that.

Also, I have not tried your last suggestion, but will do tomorrow.

@kleinesfilmroellchen – were you able to resolve this problem?

I believe that text() engages in lazy loading – the very first time it is called, there is a big hit. In the past this has been true in both PDE and Eclipse.

Here is one past discussion of the first text() operation being slow, and timing:

This might be true, but not only does text() show this behavior, but also other methods (as I said in the op) and every frame (so not just one frame at 20secs and all other at ~60fps, but all frames at 10-20secs). So I believe my problem does not lie in lazy loading.

There is some font loading & setting going on, although this also has to happen with the JAVA2D renderer and there I see no slowdown at all, solid 60fps even on my crappy laptop.

I have not yet come around to try @Architector_4 's last suggestion (as I mentioned in my previous post) but I will definitely report the results when I have time to do it.

Well, I can’t see your code, so I’m not sure. But your op made it sound like possibly you were creating a new PGraphics over and over during draw and then calling text() on the new object each draw frame – rather than creating the buffer once in setup.

If that is the case, it might still be relevant, as every frame is the the first time for that new object (and that is really inefficient even without the first-text problem). In any case, I am wishing you luck figuring out the problem.

Hi everyone, finally managed to have the time to look into this problem a bit deeper.

First, @Architector_4’s last suggestion to use P2D just for the sketch and not for the buffers did not change a thing.

I should include that I run into a runtime error thrown by some thread joiner, which has not caused a single problem yet but might be helpful:

java.lang.RuntimeException: Waited 5000ms for: <589caa7c, 565b5f1f>[count 2, qsz 0, owner <main-FPSAWTAnimator#00-Timer0>] - <main-FPSAWTAnimator#00-Timer0-FPSAWTAnimator#00-Timer1>
	at processing.opengl.PSurfaceJOGL$2.run(PSurfaceJOGL.java:410)
	at java.lang.Thread.run(Thread.java:748)

(thrown directly in first draw call after (as stated in the exception itself) 5 secs)

Problems encountered/fixed

I was actually facing some speed issues with my framerate dropping noticably to around 15fps (visible but not devastating, just disappointing) when I was drawing two PGraphics to the screen at the same time and rescaling them a bit (some fancy animations). The very last comment by @jeremydouglass was about not creating separate buffers each frame, which of course is a really bad idea.

I quickly created myself a GraphicsBuffer class (can send source code if required) which stores PGraphics for reuse each frame which means that there are at most two PGraphics objects ever created.

But additionally, during the transition animations with two visible graphics onscreen, I only drew the buffers for that transition once at the beginning and reused them until the animation is finished. I cannot do this on every draw() due to some animations on one graphics buffer itself (also user-input dependent) but this appears to be no problem as I get a solid 60fps there.

Finally, all of this increased performance, but when switching to P2D we see no difference: complete fail in that regard. There is still a per-frame drawtime of around 10 seconds and I have already optimized drawing to the amounts I can still handle in my project.

Fonts are loaded only once btw.

So there is no progress on the original problem.

If it is required I can send some more source code, but the issue appears to lie in PApplet.image(), which slows the sketch down massively (~60fps to ~ 15fps) when the rescaling of PGraphics objects drawn with this function is large. And all in all P2D still fails.

Thanks to all contributors on this problem!

If you would like help debugging from the forum then I would suggest sharing an MCVE that demonstrates the problem – some minimal code that can be switched between P2D and Java and has this dramatic slowdown. It could include your GraphicsBuffer class if you like.

One other question: have you considered upgrading to the latest Processing 3.4.x to see if that solves the problem? 3.5 is extremely new, but 3.4 has a lot of changes since 3.3.6.

1 Like

I have no more time today (europe) but I will code something up tomorrow.

My sketch uses 3.4 but I was seeing no difference in 3.3.6.

Do you need to rescale the image? Could you not just draw a scaled crop of the original? I haven’t looked at the internals, but one possible explanation is that scaling is done in the CPU. That would mean that in JAVA2D, the pixels are already in the CPU, good for scaling. But if they are in the GPU, they first have to be downloaded to the CPU to be scaled. Communication between CPU and GPU is apparently slow.
Could that be the issue? It’s possible to scale an image in the GPU, by drawing your image scaled onto a PGraphics…