Performanceprobleme mit WritableImage | Pixelbuffer

bob_harris

Mitglied
Hallo zusammen,
ich wünsche ein gesundes neues Jahr.

Um OpenGL in JavaFX zu nutzen, verwende ich LWJGL. Ich erstelle mit LWJGL einen offscreen Context (headless) und lese den
Framebuffer nach dem Rendern aus und schreibe diesen in ein ImageView.

Ich habe 2 Varianten dafür implementiert. Einmal ganz klassisch mit glReadPIxels als blockierenden Aufruf und einmal über
mehrere PBOs (PIxelBufferObject) asynchrones Auslesen. Beides funktioniert per se auch gut, vor allem beim PBO auslesen bin
ich bei ~1,x ms bis ~2,x ms unterwegs. Dort verwende ich pinned Buffer, das war nochmal etwas schneller als glMapBuffer und
glUnmapBuffer. Bei der anderen Variante ist das Auslesen etwas langsamer, aber für 60FPS immer noch sehr ausreichend.

Ich beziehe mich jetzt auf die einfache Variante, also einfaches blockierendes Auslesen mit glReadPixels.

Java:
jfxByteBuffer = MemoryUtil.memCalloc(w*4*h,1);
jfxPixelBuffer = new PixelBuffer<>(w, h, jfxByteBuffer, PixelFormat.getByteBgraPreInstance());
jfxWritableImage = new WritableImage(jfxPixelBuffer);
jfxImageView.setImage(jfxWritableImage);

Gehen wir jetzt einfach von aus, das Fenster hat die Größe 1200x800 und die oben gezeigten Buffer usw. sind entsprechend angelegt. D.h.,
das ImageView zeigt ein WritableImage und das wiederum hat als Unterbau den Pixelbuffer. Wenn nun ein Frame gerendert wurde und glReadPixels
aufgerufen wird, dann wird der Inhalt des Framebuffers in den jfxByteBuffer kopiert. Funktioniert wunderbar, Frame wird angezeigt.

Der OpenGL Kram läuft im selben Thread wie JavaFX und ich benutze den AnimationTimer, der bei Javafx so round about alle ~16,x ms das repaint event auslöst und in
meinem Fall, glReadPixels aufruft. Nachdem der Inhalt ausgelesen wurde, erfolgt noch
Code:
jfxPixelBuffer.updateBuffer(pb -> null);
damit der Inhalt des ImageViews respektive des WritableImages aktualisiert wird.

Nun habe ich aber festgestellt, das so alle ~21 Frames es keine 16,66..ms sind, sondern etwas um die 30ms (30, 31,32).
Ich hatte erst glReadPIxels unter Verdacht bzw. auch die Variante mit den PBOs, aber das ist es nicht. Sobald ich aber diese Zeile
Code:
//jfxPixelBuffer.updateBuffer(pb -> null);
auskommentiere, läuft der AnimationTimer mit seinen 16,xx ms pro Frame durch. Ich hatte auch schon andere Timervarianten probiert und dann mit Platform.runLater() aktualisiert, aber das läuft nicht smooth.

Weiß jemand, was da in den Tiefen des Pixelbuffers (JavaFX) oder WritableImage abgeht, das dieses Phänomen auslöst? Ich habe auch mal die Canvas von Javafx bemüht und dort die Frames gezeichnet, aber auch da ist mit dem AnimationTimer das selbe Problem, das sich alle ~21 Frames jemand verschluckt und ~31ms benötigt werden. Man sieht das dann auch im ImageView, das das Bild dann Springt. Ich hab zu Testzwecken einen einfachen Farbwürfel, der sich von hin und her bewegt. Und wenn dieser Fall eintritt, ist das auch wahrnehmbar.


Ich weiß, das es sowas wie DriftFX oder openglfx (husker) gibt, aber da diese Varianten ohne module-info.java (JPMS) arbeiten, fallen diese bei mir raus.

Vielleicht kann mir hier jemand helfen. ChatGPT ist auch am Ende ;)

Grüße,
Bob
 

mrBrown

Super-Moderator
Mitarbeiter
Hast du mal einen Profiler mitlaufen lassen und die RAM-Auslastung angeguckt? Wenn das regelmäßig auftritt könnte das durchaus daran liegen
 

Robert Zenz

Top Contributor
~32ms klingt im ersten Moment nach einem Problem mit VSync (wenn du 60FPS anzielst), also dass das Bild da einfach zu spaet ist und deswegen wird eines uebersprungen.

Ansonsten was @mrBrown sagt und mit VisualVM schauen ob vielleicht die Garbage Collection (oder etwas anderes) derart regelmaeszig reinhaut.
 

bob_harris

Mitglied
Hallo, vielen Dank für die Antworten. Ich werde mir das mal anschauen. Das mit den ~32ms kann ja wirklich sein, das javafx sich irgendwo verschluckt. Ist halt nur merkwürdig, das es nur beim Aktualisieren des PixelBuffers (Javafx Pixelbuffer) ist.

Grüße
 

Ähnliche Java Themen

Neue Themen


Oben