benfry / processing4

Processing 4.x releases for Java 17
https://processing.org
Other
1.34k stars 239 forks source link

RPi 4B maxes out at 36 fps running a simple example at 1920x1080 #703

Open luiscastilho opened 1 year ago

luiscastilho commented 1 year ago
## Description

I'm trying to run a simple sketch on a Raspberry Pi 4 Model B (4GB) at 1080p 60 FPS, but I can only get it to run at 36.7 FPS max. I'm using one of the examples that come with Processing (File > Examples... > Topics > Motion > Bounce). I changed it slightly, so it would run at 1080p 60 FPS and would log FPS to the console. I will post the sketch code in a comment below.

I thought that a Raspberry Pi 4 Model B would be more than enough to run simple sketches at 1080p 60 FPS. But it doesn't seem to be the case. That's what I get running this sketch:

FPS: 32.11653
FPS: 35.496437
FPS: 34.953873
FPS: 36.34715
FPS: 36.222385
FPS: 36.06623
FPS: 36.79852
FPS: 33.858864
FPS: 29.1131
FPS: 32.045887
Avg. FPS: 34.301899
Min. FPS: 29.113100
Max. FPS: 36.798519

Is that expected behavior? Note that all this sketch does in draw() is update a few variables related to position and direction and then draw an ellipse(). Is that a hardware limitation? Maybe even a Raspberry Pi 4 is more limited graphic-wise than I assumed? Or is it something on Processing side, and we might expect improvements in the future?

I opened this issue because I have an application (dungeoneering.app) that uses Processing, and I was looking forward to release a Raspberry Pi version. But I would need a lot more performance than what I'm seeing.

Let me know if there's any other info you need or tests I can do on my side. I would be glad to help.

Expected Behavior

I expected this simple sketch (Bounce example, slightly modified - code in comments below) to run at 1080p 60FPS in a Raspberry Pi 4 Model B.

Current Behavior

The sketch runs at ~34 FPS.

Steps to Reproduce

  1. Install Processing 4.2 on a Raspberry Pi OS 64-bit
  2. Open the sketch below
  3. Run

Your Environment

Possible Causes / Solutions

luiscastilho commented 1 year ago

Sketch code:

/**
 * Bounce. 
 * 
 * When the shape hits the edge of the window, it reverses its direction. 
 */

int rad = 60;        // Width of the shape
float xpos, ypos;    // Starting position of shape    

float xspeed = 2.8;  // Speed of the shape
float yspeed = 2.2;  // Speed of the shape

int xdirection = 1;  // Left or Right
int ydirection = 1;  // Top to Bottom

int countFPS = 0;
float avgFPS = 0;
float minFPS = 240;
float maxFPS = 0;

void setup() 
{
  size(1920, 1080);
  noStroke();
  frameRate(60);
  ellipseMode(RADIUS);
  // Set the starting position of the shape
  xpos = width/2;
  ypos = height/2;
}

void draw() 
{
  background(102);

  // Update the position of the shape
  xpos = xpos + ( xspeed * xdirection );
  ypos = ypos + ( yspeed * ydirection );

  // Test to see if the shape exceeds the boundaries of the screen
  // If it does, reverse its direction by multiplying by -1
  if (xpos > width-rad || xpos < rad) {
    xdirection *= -1;
  }
  if (ypos > height-rad || ypos < rad) {
    ydirection *= -1;
  }

  // Draw the shape
  ellipse(xpos, ypos, rad, rad);

  // Skip first 90 frames - waiting for FPS to stabilize
  // After that, print FPS every 30 frames and calculate avg, min and max FPS
  if (frameCount > 90 && frameCount % 30 == 0) {
    avgFPS += frameRate;
    countFPS += 1;
    if (frameRate < minFPS)
      minFPS = frameRate;
    if (frameRate > maxFPS)
      maxFPS = frameRate;
    println("FPS: " + frameRate);
  }

  // Print results and quit
  if (frameCount > 390) {
    avgFPS = avgFPS/countFPS;
    println("Avg. FPS: " + nfc(avgFPS, 6));
    println("Min. FPS: " + nfc(minFPS, 6));
    println("Max. FPS: " + nfc(maxFPS, 6));
    exit();
  }
}
benfry commented 1 year ago

Have you tried switching to P2D instead? Part of the problem with the default renderer (and why JavaFX and OpenGL are in there) is because Java2D is dreadfully slow just pushing pixels to a large(ish) screen area (I know, 1080p isn't big; but this is why it sucks).

I've not had any time to do performance testing work with RPi… The solution for you could also be as simple (err, “simple”) as messing with config options on the device for how you're using your X server, frame buffer, or even an extra command line option for starting Java to use the GL pipeline (or not use it!)