ADDITIONAL SYSTEM INFORMATION :
openjdk 11.0.15
Problem shows up on both JavaFX 11 and JavaFX 18.0.2
Problem shows up on CentOS 7 and RHEL 7. Does not show up on Windows 10.
Currently testing on the following graphics card with the proprietary nvidia drivers, although it shows up with other nvidia cards:
Graphics Vendor: NVIDIA Corporation
Renderer: Quadro GP100/PCIe/SSE2
Version: 4.6.0 NVIDIA 515.57
A DESCRIPTION OF THE PROBLEM :
The pulse loop waits for one vsync per a dirty scene. If I have multiple windows open, each with their own scene, and each scene is continuously updating (always dirty), the frame rate is 60 fps / number of windows.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create an application with multiple stages and update the contents of each stage every call to an `AnimationTimer` (make each stage constantly dirty).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Smooth, 60 frames per second animations. Adding multiple windows with simple contents should not increase the time it takes until the next pulse.
ACTUAL -
Frame rate is 60 frames per second *divided by the number of windows*. Adding multiple windows with simple, but animated contents significantly decreases the frame rate.
---------- BEGIN SOURCE ----------
package multiplescenes;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableLongValue;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultipleDirtyScenes extends Application {
private static final int SCENE_COUNT = 3;
@Override
public void start(Stage ignorePrimaryStage) {
final FramesPerSecondCounter frameRateCounter = new FramesPerSecondCounter();
frameRateCounter.start();
for (int i = 0; i < SCENE_COUNT; i++) {
final Label fpsLabel = new Label();
fpsLabel.textProperty().bind(Bindings.format("FPS: %.1f", frameRateCounter.fpsProperty())); // FPS will be ~ 60.0/SCENE_COUNT
final Label lastFrameTimeNsLabel = new Label();
lastFrameTimeNsLabel.textProperty().bind(Bindings.format("Last frame time (ns): %d", frameRateCounter.lastFrameTimeNsProperty())); // Makes the scene constantly dirty
final Scene scene = new Scene(new VBox(fpsLabel, lastFrameTimeNsLabel), 480, 100);
final Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
public static void main(String[] args) {
launch();
}
private static class FramesPerSecondCounter extends AnimationTimer {
private static final int FRAME_TIME_COUNT = 10;
private final long[] frameTimesNs = new long[FRAME_TIME_COUNT];
private int frameTimeIndex = 0;
private final LongProperty lastFrameTimeNs = new SimpleLongProperty();
private final DoubleProperty fpsValue = new SimpleDoubleProperty();
@Override
public void handle(final long nowNs) {
lastFrameTimeNs.set(nowNs);
final long oldFrameTimeNs = frameTimesNs[frameTimeIndex];
frameTimesNs[frameTimeIndex] = nowNs;
frameTimeIndex = (frameTimeIndex + 1) % frameTimesNs.length;
final long elapsedNanos = nowNs - oldFrameTimeNs;
final long elapsedNanosPerFrame = elapsedNanos / frameTimesNs.length;
final double fps = 1_000_000_000.0 / elapsedNanosPerFrame;
fpsValue.set(fps);
}
public ObservableDoubleValue fpsProperty() {
return fpsValue;
}
public ObservableLongValue lastFrameTimeNsProperty() {
return lastFrameTimeNs;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use *both* `-Dprism.vsync=false` and environment variable `__GL_SYNC_TO_VBLANK=0` (see https://bugs.openjdk.org/browse/JDK-8168366).
FREQUENCY : always
openjdk 11.0.15
Problem shows up on both JavaFX 11 and JavaFX 18.0.2
Problem shows up on CentOS 7 and RHEL 7. Does not show up on Windows 10.
Currently testing on the following graphics card with the proprietary nvidia drivers, although it shows up with other nvidia cards:
Graphics Vendor: NVIDIA Corporation
Renderer: Quadro GP100/PCIe/SSE2
Version: 4.6.0 NVIDIA 515.57
A DESCRIPTION OF THE PROBLEM :
The pulse loop waits for one vsync per a dirty scene. If I have multiple windows open, each with their own scene, and each scene is continuously updating (always dirty), the frame rate is 60 fps / number of windows.
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create an application with multiple stages and update the contents of each stage every call to an `AnimationTimer` (make each stage constantly dirty).
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Smooth, 60 frames per second animations. Adding multiple windows with simple contents should not increase the time it takes until the next pulse.
ACTUAL -
Frame rate is 60 frames per second *divided by the number of windows*. Adding multiple windows with simple, but animated contents significantly decreases the frame rate.
---------- BEGIN SOURCE ----------
package multiplescenes;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.beans.binding.Bindings;
import javafx.beans.property.DoubleProperty;
import javafx.beans.property.LongProperty;
import javafx.beans.property.SimpleDoubleProperty;
import javafx.beans.property.SimpleLongProperty;
import javafx.beans.value.ObservableDoubleValue;
import javafx.beans.value.ObservableLongValue;
import javafx.scene.Scene;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;
public class MultipleDirtyScenes extends Application {
private static final int SCENE_COUNT = 3;
@Override
public void start(Stage ignorePrimaryStage) {
final FramesPerSecondCounter frameRateCounter = new FramesPerSecondCounter();
frameRateCounter.start();
for (int i = 0; i < SCENE_COUNT; i++) {
final Label fpsLabel = new Label();
fpsLabel.textProperty().bind(Bindings.format("FPS: %.1f", frameRateCounter.fpsProperty())); // FPS will be ~ 60.0/SCENE_COUNT
final Label lastFrameTimeNsLabel = new Label();
lastFrameTimeNsLabel.textProperty().bind(Bindings.format("Last frame time (ns): %d", frameRateCounter.lastFrameTimeNsProperty())); // Makes the scene constantly dirty
final Scene scene = new Scene(new VBox(fpsLabel, lastFrameTimeNsLabel), 480, 100);
final Stage stage = new Stage();
stage.setScene(scene);
stage.show();
}
}
public static void main(String[] args) {
launch();
}
private static class FramesPerSecondCounter extends AnimationTimer {
private static final int FRAME_TIME_COUNT = 10;
private final long[] frameTimesNs = new long[FRAME_TIME_COUNT];
private int frameTimeIndex = 0;
private final LongProperty lastFrameTimeNs = new SimpleLongProperty();
private final DoubleProperty fpsValue = new SimpleDoubleProperty();
@Override
public void handle(final long nowNs) {
lastFrameTimeNs.set(nowNs);
final long oldFrameTimeNs = frameTimesNs[frameTimeIndex];
frameTimesNs[frameTimeIndex] = nowNs;
frameTimeIndex = (frameTimeIndex + 1) % frameTimesNs.length;
final long elapsedNanos = nowNs - oldFrameTimeNs;
final long elapsedNanosPerFrame = elapsedNanos / frameTimesNs.length;
final double fps = 1_000_000_000.0 / elapsedNanosPerFrame;
fpsValue.set(fps);
}
public ObservableDoubleValue fpsProperty() {
return fpsValue;
}
public ObservableLongValue lastFrameTimeNsProperty() {
return lastFrameTimeNs;
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
Use *both* `-Dprism.vsync=false` and environment variable `__GL_SYNC_TO_VBLANK=0` (see https://bugs.openjdk.org/browse/JDK-8168366).
FREQUENCY : always
- duplicates
-
JDK-8298870 Frame rate drops as number with number of Stages with animation
-
- Closed
-
- relates to
-
JDK-8168366 vsync is always on with Ubuntu and nVidia proprietary drivers
-
- Open
-
-
JDK-8298870 Frame rate drops as number with number of Stages with animation
-
- Closed
-