Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calling PShape.translate(), PShape.rotate() etc creates and stores a new PMatrix #5685

Closed
hamoid opened this issue Oct 19, 2018 · 19 comments

Comments

Projects
None yet
4 participants
@hamoid
Copy link
Contributor

commented Oct 19, 2018

I opened this issue because of a performance issue with Retained particles, but you can directly jump to my answer to see the actual issue.

Description

Running the DynamicParticlesRetained often drops frames (high numbers, up to 15 frames late) on an Nvidia GTX 1060. Running the DynamicParticlesImmediate performs much better and shows no such issue.

Expected Behavior

Retained is supposed to perform better than Immediate mode. Frames should not be dropped at that rate.

Current Behavior

Frames are frequently dropped and the animation is full of jitter due to long pauses.

Steps to Reproduce

To produce actual data and not just a subjective impression, I opened both DynamicParticlesRetained and DynamicParticlesImmediate and made the following changes:

// add this global
long lastTime;

// make sure the frameRate is 60 inside setup()
frameRate(60);

// insert these lines at the top of draw(), before background(0). 
// They will print the delay since the last frame in milliseconds 
// if it's above 20ms (at 60 fps the expected value is 16.666ms)
void draw () {
  long nuTime = System.nanoTime();
  float diff = (nuTime - lastTime) / 1000000.0;
  if(diff > 20) {
    println(diff, hour() + ":" + nf(minute(), 2) + ":" + nf(second(), 2));
  }
  lastTime = nuTime; 
  
  background(0);

// comment out
//     println("fps: " + frate);

Run each sketch for one minute leaving the mouse at the top border and observe the console.

Immediate mode

9 frames were shown as late (a few more were visible but not detected due to the 20ms threshold), subtle jitter (1 frame late).

1.6332468E7 19:44:58
50.23394 19:44:58
20.017307 19:44:59
26.053064 19:45:21
21.748043 19:45:40
25.529957 19:45:41
20.312368 19:45:43
20.26308 19:45:45
21.835554 19:45:47
20.920164 19:45:52

Retained mode (many frames were late, visible hiccups)

52 frames were shown as late, with very visible pauses. 259 ms at 60fps is about 15 frames late.

1.6496129E7 19:47:42
104.17787 19:47:42
21.417135 19:47:42
198.30045 19:47:43
21.605522 19:47:44
30.506672 19:47:44
34.44974 19:47:46
49.50074 19:47:47
302.4965 19:47:48
29.086777 19:47:49
64.352455 19:47:49
221.59677 19:47:50
68.06031 19:47:51
63.470654 19:47:52
224.25464 19:47:53
69.465866 19:47:55
70.64256 19:47:56
21.7029 19:47:58
72.15584 19:47:58
259.8315 19:48:00
51.579815 19:48:01
67.42985 19:48:03
76.251785 19:48:04
88.897095 19:48:06
106.75623 19:48:07
257.9176 19:48:09
56.207336 19:48:10
70.09778 19:48:11
77.51151 19:48:12
67.30514 19:48:14
69.65708 19:48:15
79.876305 19:48:16
256.2453 19:48:18
46.30062 19:48:19
59.963913 19:48:20
89.71463 19:48:22
63.56876 19:48:23
242.00153 19:48:24
51.244728 19:48:26
61.695816 19:48:27
65.01016 19:48:29
22.264074 19:48:29
20.493372 19:48:29
70.53066 19:48:30
254.26923 19:48:32
54.74097 19:48:33
20.940067 19:48:34
78.707054 19:48:35
89.770195 19:48:36
68.60402 19:48:38
259.58456 19:48:40
21.321068 19:48:41
57.82642 19:48:41

Maybe I made some mistake in the numbers, but the difference between the two approaches is very noticeable by looking at the screen.

Your Environment

Processing 3.4, Ubuntu 18.04, Zotac Magnus computer with 8Gb RAM (VR capable computer with a GTX 1060).

Possible Causes / Solutions

I suspect this line (PShape.translate(...))

part.translate(velocities[n].x, velocities[n].y);

which is only present in the retained mode example.

@hamoid

This comment has been minimized.

Copy link
Contributor Author

commented Oct 23, 2018

Could the reason be that in https://github.com/processing/processing/blob/master/core/src/processing/opengl/PShapeOpenGL.java a call to transform() calls pushTransform() (each time we would do translate for a particle, for instance) which creates a new PMatrix3D and adds it to transformStack, but those piling matrices are never removed until the user calls resetMatrix?

This might be confirmed by the fact that running this program keeps using more and more memory until the system slows down to crawl even with a powerful graphics card (after less than one minute):

PShape group;

void setup() {  
  size(600, 600, P3D);
  noStroke();
  group = createShape(GROUP);
  for (int i = 0; i < 15000; i++) {
    PShape s = createShape(BOX, 5);
    s.translate(random(width), random(height));
    group.addChild(s);
  }
}
void draw() {
  background(0);
  PShape[] shapes = group.getChildren(); 
  for (int i = 0; i < shapes.length; i++) {
    shapes[i].translate(random(-1, 1), random(-1, 1));
  }
  shape(group);
  if(frameCount % 60 == 0) {
    println(frameRate);
  }
}

By replacing the second .translate() call with the following the memory usage grows at a much slower rate.

shapes[i].resetMatrix();
shapes[i].translate(random(width), random(height));

@codeanticode ?

@hamoid hamoid changed the title Retained mode example performing worse than Immediate mode Calling PShape.translate(), PShape.rotate() etc creates and stores a new PMatrix Oct 23, 2018

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Nov 2, 2018

In the DynamicParticlesRetained example, if one sets npartTotal = 60000 if grinds to a halt in a few seconds on a fast graphics card...

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Nov 22, 2018

Any hope of seeing this fixed ? If I can help I'd be happy to but not sure how.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Dec 28, 2018

anyone ???

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Jan 6, 2019

Is it possible that this problem will be fixed sometime soon ? Thanks

@codeanticode

This comment has been minimized.

Copy link
Member

commented Jan 10, 2019

@PratiquesAlgorithmiques I will look at it today!

@codeanticode

This comment has been minimized.

Copy link
Member

commented Jan 10, 2019

@hamoid the creation of the PMatrix objects does indeed slow down the particle system, and their use can be actually removed by updating the inverse transformation at each step so no need to store the individual transformations in a matrix stack. By using this more efficient approach, there are much fewer dropped frames. This is the commit that implements this approach: 93bc3bd

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Jan 14, 2019

many thanks codeanticode ! any idea when will this version be available ? Even if I try something like the following in my program :

PShape[] shapes = group.getChildren();
for (int i = 0; i < shapes.length; i++) {
shapes[i].resetMatrix();
shapes[i].translate(random(width), random(height), random(depth));
}
shape(group);

it is very slow (16 fps).
if i remove these two lines it is 120 fps

but maybe the commit changes other things ?
thanks in any case

@codeanticode

This comment has been minimized.

Copy link
Member

commented Jan 16, 2019

There were several other fixes committed recently to the main branch, so I'd imagine that a new version will come out soon.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Jan 23, 2019

i just downloaded 3.5.2 but i still have the same bottleneck with shapes[i].translate where shapes.length = 62500 (cubes). it drops from 120fps to 16fps when i add shapes[i].translate

shapes = thisModel.getChildren();

for (int i = 0; i < shapes.length; i++) {
shapes[i].resetMatrix();
shapes[i].translate(m.x, m.y, m.z);
}

shape(thisModel);

anyone for a fix ?
thanks

@codeanticode

This comment has been minimized.

Copy link
Member

commented Jan 23, 2019

@PratiquesAlgorithmiques there is a limit to what you can do with PShape. It can greatly improve performance provided that the geometry remains unchanged, since it can then be copied to the GPU memory just one time. If you are modifying all the vertices in each frame, then this performance advantage is lost since Processing has to copy the modified geometry to the GPU every time. In that case, it might be faster to use immediate mode, this is, just regular drawing calls without PShape.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Jan 24, 2019

thanks for your response codeanticode ! in fact it is just 62500 cubes. i change their position every frame and occasionally their color with .setFill. But that is all. PShape should work for that no ? It worked great with GLGraphics.

@codeanticode

This comment has been minimized.

Copy link
Member

commented Jan 25, 2019

Ok, I believe there are some situations where the geometry changes may impact less the rendering performance, but need to take a closer look.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Jan 26, 2019

thanks for looking into it because i've been trying to port my 151 + GLGraphics project to P3 for a long time !

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Mar 2, 2019

I tried the 3.5.3 version but same bottleneck.
it is definitely the shapes[i].translate line that slows everything way down.

for (int i = 0; i < shapes.length; i++) {
shapes[i].resetMatrix();
shapes[i].translate(m.x, m.y, m.z);
}
it is so frustrating because i don't know what to do to move forward. I absolutely need to port my very long 151 + GLGraphics program to P3 very soon. any suggestions, anyone ? help !

@neilcsmith-net

This comment has been minimized.

Copy link

commented Mar 4, 2019

Also check out https://discourse.processing.org/t/pshape-resetmatrix-not-resetting-rotation-in-p2d/8508 which suggests there might be some issues with this fix so far.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Mar 5, 2019

neilcsmith-net I tried the matrix = new PMatrix3D(); trick but fps is the same ; (

@neilcsmith-net

This comment has been minimized.

Copy link

commented Mar 5, 2019

@PratiquesAlgorithmiques sorry, it wasn't intended as a suggestion for a workaround - more a heads up for @codeanticode that this appears to have also caused a regression somewhere.

@PratiquesAlgorithmiques

This comment has been minimized.

Copy link

commented Mar 20, 2019

ok thanks @neilcsmith-net

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.