Thread: [sdljava-users] Usage example for glGetDoublev
Status: Beta
Brought to you by:
ivan_ganza
From: Gregor <Gre...@gm...> - 2005-09-08 20:28:05
|
Hi! I"m trying to use glGetDoublev to read back the modelview and projection matrices from OpenGL. However, it looks like I'm doing something wrong with the DoubleBuffers required for that. What I'm doing basically is in this code: GlewImpl gl; private ml.math.Matrix4 modelViewMatrix; private ml.math.Matrix4 projectionMatrix; private double viewFieldOfView; private DoubleBuffer matrixBuffer; public ViewWindowSpace(Widget parent) { super(); matrixBuffer=DoubleBuffer.allocate(16); modelViewMatrix=new Matrix4(); projectionMatrix=new Matrix4(); currentRenderMode=RenderMode.Solid; initGLContext(); // snip: unrelated code addListener(new LifeCycleListener() { public void lifeCycleEvent(LifeCycleEvent e) { // TODO Auto-generated method stub if(e.getType()==LifeCycleEvent.Type.REALIZE) { setupViewingAreaInitial(); } } } // snip: unrelated code } protected void setupViewingAreaInitial() { viewFieldOfView=45.0; glBegin(); GlewJNI.SWIG_glew_init(); gl=new GlewImpl(); int width = getWidth(); int height = getHeight(); gl.glViewport(0, 0, width, height); gl.glMatrixMode(GL.GL_PROJECTION); // select the projection matrix gl.glLoadIdentity(); // reset the projection matrix float fAspect = (float) width / (float) height; gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview matrix gl.glLoadIdentity(); gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); projectionMatrix.setFromOpenGLMatrix(matrixBuffer); glEnd(); } What this does: The constructor allocates the DoubleBuffer in question and registers an event handler to do the rest of the initialilsation once the opengl context can actually be used. When this is the case, setupViewingAreaInitial is called to perform the init of the gl context. This fails with a NullPointerException in the first call to gl.glGetDoublev(). The console output for this exception is as follows: Exception in thread "main" java.lang.NullPointerException: null address returned from GetDirectBufferAddress() call. Make sure the buffer is a _direct_ buffer. at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:143) at ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowSpace.java:322) at ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.java:277) at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) at org.gnu.gtk.Widget.handleRealize(Widget.java:764) at org.gnu.gtk.Widget.gtk_widget_show(Native Method) at org.gnu.gtk.Widget.show(Widget.java:119) at ml.core.State.createMainWindow(State.java:158) at ml.ML3D.<init>(ML3D.java:49) at ml.ML3D.main(ML3D.java:66) I have no clue why this happens. Do I initialize the DoubleBuffer in question badly? Is there any example that shows how it should be done? Any help would be appreciated. Regards, Gregor |
From: Ivan Z. G. <iva...@ya...> - 2005-09-09 02:12:15
|
Hi Gregor, I'm glad to see this stuff being used! There doesn't seem to be anything wrong with your code. The problem is that the VM isn't returning a direct buffer.=20 Unfortunately the VM doesn't seem to support direct buffers. What type of VM are you using? See here:=20 http://java.sun.com/j2se/1.4.2/docs/guide/jni/jni-14.html#GetDirectBuffer= Address -Ivan/ Gregor M=FCckl wrote: >Hi! > >I"m trying to use glGetDoublev to read back the modelview and projection= =20 >matrices from OpenGL. However, it looks like I'm doing something wrong w= ith=20 >the DoubleBuffers required for that. > >What I'm doing basically is in this code: > > GlewImpl gl; > private ml.math.Matrix4 modelViewMatrix; > private ml.math.Matrix4 projectionMatrix; > private double viewFieldOfView; > private DoubleBuffer matrixBuffer; > > public ViewWindowSpace(Widget parent)=20 > { > super(); > > matrixBuffer=3DDoubleBuffer.allocate(16); > modelViewMatrix=3Dnew Matrix4(); > projectionMatrix=3Dnew Matrix4(); > =09 > currentRenderMode=3DRenderMode.Solid; > > initGLContext(); > > // snip: unrelated code > > addListener(new LifeCycleListener() { > > public void lifeCycleEvent(LifeCycleEvent e) > { > // TODO Auto-generated method stub > if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { > setupViewingAreaInitial(); > } > =20 > } > } > > // snip: unrelated code > } > > protected void setupViewingAreaInitial()=20 > { > viewFieldOfView=3D45.0; > =20 > glBegin(); > GlewJNI.SWIG_glew_init(); > gl=3Dnew GlewImpl(); > int width =3D getWidth(); > int height =3D getHeight(); > gl.glViewport(0, 0, width, height); =20 > gl.glMatrixMode(GL.GL_PROJECTION); // select the projection= =20 >matrix > gl.glLoadIdentity(); // reset the=20 >projection matrix > float fAspect =3D (float) width / (float) height; > gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); > gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview = matrix > gl.glLoadIdentity(); > > gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); > modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); > gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); > projectionMatrix.setFromOpenGLMatrix(matrixBuffer); > =20 > glEnd(); > } > >What this does: > >The constructor allocates the DoubleBuffer in question and registers an = event=20 >handler to do the rest of the initialilsation once the opengl context ca= n=20 >actually be used. When this is the case, setupViewingAreaInitial is call= ed to=20 >perform the init of the gl context. This fails with a NullPointerExcepti= on in >the first call to gl.glGetDoublev(). The console output for this except= ion is=20 >as follows: > >Exception in thread "main" java.lang.NullPointerException: null address=20 >returned from GetDirectBufferAddress() call. Make sure the buffer is a=20 >_direct_ buffer. > at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) > at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:143) > at=20 >ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowSpa= ce.java:322) > at=20 >ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.java= :277) > at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) > at org.gnu.gtk.Widget.handleRealize(Widget.java:764) > at org.gnu.gtk.Widget.gtk_widget_show(Native Method) > at org.gnu.gtk.Widget.show(Widget.java:119) > at ml.core.State.createMainWindow(State.java:158) > at ml.ML3D.<init>(ML3D.java:49) > at ml.ML3D.main(ML3D.java:66) > >I have no clue why this happens. Do I initialize the DoubleBuffer in que= stion=20 >badly? Is there any example that shows how it should be done? Any help w= ould=20 >be appreciated. > >Regards, >Gregor > > >------------------------------------------------------- >SF.Net email is Sponsored by the Better Software Conference & EXPO >September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practi= ces >Agile & Plan-Driven Development * Managing Projects & Teams * Testing & = QA >Security * Process Improvement & Measurement * http://www.sqe.com/bsce5s= f >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > =20 > |
From: Ivan Z. G. <iva...@ya...> - 2005-09-09 23:38:13
|
Gregor, I had a look in the code and intact SDLSurface isn't a good example because the buffer is created in the native code. Have a look at ByteBufferPool instead. -Ivan/ Gregor M=FCckl wrote: >Hi! > >I"m trying to use glGetDoublev to read back the modelview and projection= =20 >matrices from OpenGL. However, it looks like I'm doing something wrong w= ith=20 >the DoubleBuffers required for that. > >What I'm doing basically is in this code: > > GlewImpl gl; > private ml.math.Matrix4 modelViewMatrix; > private ml.math.Matrix4 projectionMatrix; > private double viewFieldOfView; > private DoubleBuffer matrixBuffer; > > public ViewWindowSpace(Widget parent)=20 > { > super(); > > matrixBuffer=3DDoubleBuffer.allocate(16); > modelViewMatrix=3Dnew Matrix4(); > projectionMatrix=3Dnew Matrix4(); > =09 > currentRenderMode=3DRenderMode.Solid; > > initGLContext(); > > // snip: unrelated code > > addListener(new LifeCycleListener() { > > public void lifeCycleEvent(LifeCycleEvent e) > { > // TODO Auto-generated method stub > if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { > setupViewingAreaInitial(); > } > =20 > } > } > > // snip: unrelated code > } > > protected void setupViewingAreaInitial()=20 > { > viewFieldOfView=3D45.0; > =20 > glBegin(); > GlewJNI.SWIG_glew_init(); > gl=3Dnew GlewImpl(); > int width =3D getWidth(); > int height =3D getHeight(); > gl.glViewport(0, 0, width, height); =20 > gl.glMatrixMode(GL.GL_PROJECTION); // select the projection= =20 >matrix > gl.glLoadIdentity(); // reset the=20 >projection matrix > float fAspect =3D (float) width / (float) height; > gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); > gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview = matrix > gl.glLoadIdentity(); > > gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); > modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); > gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); > projectionMatrix.setFromOpenGLMatrix(matrixBuffer); > =20 > glEnd(); > } > >What this does: > >The constructor allocates the DoubleBuffer in question and registers an = event=20 >handler to do the rest of the initialilsation once the opengl context ca= n=20 >actually be used. When this is the case, setupViewingAreaInitial is call= ed to=20 >perform the init of the gl context. This fails with a NullPointerExcepti= on in >the first call to gl.glGetDoublev(). The console output for this except= ion is=20 >as follows: > >Exception in thread "main" java.lang.NullPointerException: null address=20 >returned from GetDirectBufferAddress() call. Make sure the buffer is a=20 >_direct_ buffer. > at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) > at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:143) > at=20 >ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowSpa= ce.java:322) > at=20 >ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.java= :277) > at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) > at org.gnu.gtk.Widget.handleRealize(Widget.java:764) > at org.gnu.gtk.Widget.gtk_widget_show(Native Method) > at org.gnu.gtk.Widget.show(Widget.java:119) > at ml.core.State.createMainWindow(State.java:158) > at ml.ML3D.<init>(ML3D.java:49) > at ml.ML3D.main(ML3D.java:66) > >I have no clue why this happens. Do I initialize the DoubleBuffer in que= stion=20 >badly? Is there any example that shows how it should be done? Any help w= ould=20 >be appreciated. > >Regards, >Gregor > > >------------------------------------------------------- >SF.Net email is Sponsored by the Better Software Conference & EXPO >September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practi= ces >Agile & Plan-Driven Development * Managing Projects & Teams * Testing & = QA >Security * Process Improvement & Measurement * http://www.sqe.com/bsce5s= f >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > =20 > |
From: Gregor <Gre...@gm...> - 2005-09-10 11:39:13
|
Hi, Ivan! Thanks for your help. Indeed, ByteBuffer.allocateDirect() is the right=20 solution and it seems to work now. I cannot tell for sure yet as the=20 gtk-based input handling is still not working properly and I therefore can'= t=20 navigate the 3D view. However, I feel that relyinig on java.nio.ByteBuffer and derivates is a bit= =20 strange, especially given their somewhat peculiar design. Looking at the co= de=20 I have now which has to copy data to newly created buffers every time I nee= d=20 to pass an array to OpenGL, I get the feeling that this slower than dealing= =20 directly with arrays, which are readiy available in my case and probably mo= re=20 optimizeable by the Java compiler and JVM. What was the reason for using these buffers instead of arrays? Am I missing= =20 something here? Regards, Gregor On Saturday 10 September 2005 01:37, Ivan Z. Ganza wrote: > Gregor, > > I had a look in the code and intact SDLSurface isn't a good example > because the buffer is created in the native code. Have a look at > ByteBufferPool instead. > > -Ivan/ > > Gregor M=FCckl wrote: > >Hi! > > > >I"m trying to use glGetDoublev to read back the modelview and projection > >matrices from OpenGL. However, it looks like I'm doing something wrong > > with the DoubleBuffers required for that. > > > >What I'm doing basically is in this code: > > > > GlewImpl gl; > > private ml.math.Matrix4 modelViewMatrix; > > private ml.math.Matrix4 projectionMatrix; > > private double viewFieldOfView; > > private DoubleBuffer matrixBuffer; > > > > public ViewWindowSpace(Widget parent) > > { > > super(); > > > > matrixBuffer=3DDoubleBuffer.allocate(16); > > modelViewMatrix=3Dnew Matrix4(); > > projectionMatrix=3Dnew Matrix4(); > > > > currentRenderMode=3DRenderMode.Solid; > > > > initGLContext(); > > > > // snip: unrelated code > > > > addListener(new LifeCycleListener() { > > > > public void lifeCycleEvent(LifeCycleEvent e) > > { > > // TODO Auto-generated method stub > > if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { > > setupViewingAreaInitial(); > > } > > > > } > > } > > > > // snip: unrelated code > > } > > > > protected void setupViewingAreaInitial() > > { > > viewFieldOfView=3D45.0; > > > > glBegin(); > > GlewJNI.SWIG_glew_init(); > > gl=3Dnew GlewImpl(); > > int width =3D getWidth(); > > int height =3D getHeight(); > > gl.glViewport(0, 0, width, height); > > gl.glMatrixMode(GL.GL_PROJECTION); // select the projection > >matrix > > gl.glLoadIdentity(); // reset the > >projection matrix > > float fAspect =3D (float) width / (float) height; > > gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); > > gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview > > matrix gl.glLoadIdentity(); > > > > gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); > > modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); > > gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); > > projectionMatrix.setFromOpenGLMatrix(matrixBuffer); > > > > glEnd(); > > } > > > >What this does: > > > >The constructor allocates the DoubleBuffer in question and registers an > > event handler to do the rest of the initialilsation once the opengl > > context can actually be used. When this is the case, > > setupViewingAreaInitial is called to perform the init of the gl context. > > This fails with a NullPointerException in the first call to=20 > > gl.glGetDoublev(). The console output for this exception is as follows: > > > >Exception in thread "main" java.lang.NullPointerException: null address > >returned from GetDirectBufferAddress() call. Make sure the buffer is a > >_direct_ buffer. > > at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) > > at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:143) > > at > >ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowSpa= ce > >.java:322) at > >ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.java= :2 > >77) at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) > > at org.gnu.gtk.Widget.handleRealize(Widget.java:764) > > at org.gnu.gtk.Widget.gtk_widget_show(Native Method) > > at org.gnu.gtk.Widget.show(Widget.java:119) > > at ml.core.State.createMainWindow(State.java:158) > > at ml.ML3D.<init>(ML3D.java:49) > > at ml.ML3D.main(ML3D.java:66) > > > >I have no clue why this happens. Do I initialize the DoubleBuffer in > > question badly? Is there any example that shows how it should be done? > > Any help would be appreciated. > > > >Regards, > >Gregor > > > > > >------------------------------------------------------- > >SF.Net email is Sponsored by the Better Software Conference & EXPO > >September 19-22, 2005 * San Francisco, CA * Development Lifecycle > > Practices Agile & Plan-Driven Development * Managing Projects & Teams * > > Testing & QA Security * Process Improvement & Measurement * > > http://www.sqe.com/bsce5sf > > _______________________________________________ > >sdljava-users mailing list > >sdl...@li... > >https://lists.sourceforge.net/lists/listinfo/sdljava-users > > ------------------------------------------------------- > SF.Net email is Sponsored by the Better Software Conference & EXPO > September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practic= es > Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA > Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf > _______________________________________________ > sdljava-users mailing list > sdl...@li... > https://lists.sourceforge.net/lists/listinfo/sdljava-users |
From: Ivan Z. G. <iva...@ya...> - 2005-09-10 21:39:24
|
Hi Gregor, The direct buffers introduced with NIO are better than sliced bread...:-) Without them I don't think it would be possible to achieve any level of meaningfully performance. A direct buffer is mapped directly to a region of memory inside the JVM's memory space. When you perform operations on a direct buffer they effect the memory directly and thus and are very fast. The other option is to copy the data each time from the JVM's memory space into the native code space (or visa versa). The copy method is an order of magnitude slower. First the new array must be allocated. Then the data must be copied into the array each time. For an idea of the speed difference look at the difference in execution time between updating the screen using the two methods: =20 ByteBuffer getPixelData() and public void setPixelData32(int[] pixelData) If you are using these direct buffers you should allocate all the buffers you need before doing anything. Then utilize them later however you wish. Otherwise the performance will be much worse if a new one is constantly created. Notice that getPixelData() only creates the buffer once. The buffer directly has access to the data of the surface! =20 -Ivan/ Gregor M=FCckl wrote: >Hi, Ivan! > >Thanks for your help. Indeed, ByteBuffer.allocateDirect() is the right=20 >solution and it seems to work now. I cannot tell for sure yet as the=20 >gtk-based input handling is still not working properly and I therefore c= an't=20 >navigate the 3D view. > >However, I feel that relyinig on java.nio.ByteBuffer and derivates is a = bit=20 >strange, especially given their somewhat peculiar design. Looking at the= code=20 >I have now which has to copy data to newly created buffers every time I = need=20 >to pass an array to OpenGL, I get the feeling that this slower than deal= ing=20 >directly with arrays, which are readiy available in my case and probably= more=20 >optimizeable by the Java compiler and JVM. > >What was the reason for using these buffers instead of arrays? Am I miss= ing=20 >something here? > >Regards, >Gregor > >On Saturday 10 September 2005 01:37, Ivan Z. Ganza wrote: > =20 > >>Gregor, >> >>I had a look in the code and intact SDLSurface isn't a good example >>because the buffer is created in the native code. Have a look at >>ByteBufferPool instead. >> >>-Ivan/ >> >>Gregor M=FCckl wrote: >> =20 >> >>>Hi! >>> >>>I"m trying to use glGetDoublev to read back the modelview and projecti= on >>>matrices from OpenGL. However, it looks like I'm doing something wrong >>>with the DoubleBuffers required for that. >>> >>>What I'm doing basically is in this code: >>> >>> GlewImpl gl; >>> private ml.math.Matrix4 modelViewMatrix; >>> private ml.math.Matrix4 projectionMatrix; >>> private double viewFieldOfView; >>> private DoubleBuffer matrixBuffer; >>> >>> public ViewWindowSpace(Widget parent) >>> { >>> super(); >>> >>> matrixBuffer=3DDoubleBuffer.allocate(16); >>> modelViewMatrix=3Dnew Matrix4(); >>> projectionMatrix=3Dnew Matrix4(); >>> >>> currentRenderMode=3DRenderMode.Solid; >>> >>> initGLContext(); >>> >>> // snip: unrelated code >>> >>> addListener(new LifeCycleListener() { >>> >>> public void lifeCycleEvent(LifeCycleEvent e) >>> { >>> // TODO Auto-generated method stub >>> if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { >>> setupViewingAreaInitial(); >>> } >>> >>> } >>> } >>> >>> // snip: unrelated code >>> } >>> >>> protected void setupViewingAreaInitial() >>> { >>> viewFieldOfView=3D45.0; >>> >>> glBegin(); >>> GlewJNI.SWIG_glew_init(); >>> gl=3Dnew GlewImpl(); >>> int width =3D getWidth(); >>> int height =3D getHeight(); >>> gl.glViewport(0, 0, width, height); >>> gl.glMatrixMode(GL.GL_PROJECTION); // select the projectio= n >>>matrix >>> gl.glLoadIdentity(); // reset the >>>projection matrix >>> float fAspect =3D (float) width / (float) height; >>> gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); >>> gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview >>>matrix gl.glLoadIdentity(); >>> >>> gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); >>> modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); >>> gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); >>> projectionMatrix.setFromOpenGLMatrix(matrixBuffer); >>> >>> glEnd(); >>> } >>> >>>What this does: >>> >>>The constructor allocates the DoubleBuffer in question and registers a= n >>>event handler to do the rest of the initialilsation once the opengl >>>context can actually be used. When this is the case, >>>setupViewingAreaInitial is called to perform the init of the gl contex= t. >>>This fails with a NullPointerException in the first call to=20 >>>gl.glGetDoublev(). The console output for this exception is as follows= : >>> >>>Exception in thread "main" java.lang.NullPointerException: null addres= s >>>returned from GetDirectBufferAddress() call. Make sure the buffer is = a >>>_direct_ buffer. >>> at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) >>> at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:14= 3) >>> at >>>ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowS= pace >>>.java:322) at >>>ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.ja= va:2 >>>77) at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) >>> at org.gnu.gtk.Widget.handleRealize(Widget.java:764) >>> at org.gnu.gtk.Widget.gtk_widget_show(Native Method) >>> at org.gnu.gtk.Widget.show(Widget.java:119) >>> at ml.core.State.createMainWindow(State.java:158) >>> at ml.ML3D.<init>(ML3D.java:49) >>> at ml.ML3D.main(ML3D.java:66) >>> >>>I have no clue why this happens. Do I initialize the DoubleBuffer in >>>question badly? Is there any example that shows how it should be done? >>>Any help would be appreciated. >>> >>>Regards, >>>Gregor >>> >>> >>>------------------------------------------------------- >>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams = * >>>Testing & QA Security * Process Improvement & Measurement * >>>http://www.sqe.com/bsce5sf >>>_______________________________________________ >>>sdljava-users mailing list >>>sdl...@li... >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>> =20 >>> >>------------------------------------------------------- >>SF.Net email is Sponsored by the Better Software Conference & EXPO >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle Pract= ices >>Agile & Plan-Driven Development * Managing Projects & Teams * Testing &= QA >>Security * Process Improvement & Measurement * http://www.sqe.com/bsce5= sf >>_______________________________________________ >>sdljava-users mailing list >>sdl...@li... >>https://lists.sourceforge.net/lists/listinfo/sdljava-users >> =20 >> > > >------------------------------------------------------- >SF.Net email is Sponsored by the Better Software Conference & EXPO >September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practi= ces >Agile & Plan-Driven Development * Managing Projects & Teams * Testing & = QA >Security * Process Improvement & Measurement * http://www.sqe.com/bsce5s= f >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > =20 > |
From: Gregor <Gre...@gm...> - 2005-09-11 10:37:20
|
Hi! My problem is that I really have to allocate these direct buffers on demand= =20 for something like one or two opengl calls each. Furthermore, they really a= re=20 quite small. The biggest buffer I use that way is there to store a matrix o= f=20 4x4 doubles, that is, 128 bytes. Using byte buffers may be a valid approach when working on large, uniform=20 amounts of data like framebuffers. But that is not the case with geometry=20 data for OpenGL. Using vertex arrays is almost out of question for me since= =20 the geometry data I have is very dynamic in every way. Well, this is not trying to be a rant. I'm just not yet convinced that this= is=20 the right approach. It looks like far too much overhead to me, making all t= he=20 OpenGL functions taking (small) arrays practically useless. Maybe some=20 benchmarking is in order to get some definitive answers, but I don't have=20 enough time for that. Regards, Gregor On Saturday 10 September 2005 23:39, Ivan Z. Ganza wrote: > Hi Gregor, > > The direct buffers introduced with NIO are better than sliced > bread...:-) Without them I don't think it would be possible to achieve > any level of meaningfully performance. > > A direct buffer is mapped directly to a region of memory inside the > JVM's memory space. When you perform operations on a direct buffer they > effect the memory directly and thus and are very fast. The other option > is to copy the data each time from the JVM's memory space into the > native code space (or visa versa). The copy method is an order of > magnitude slower. First the new array must be allocated. Then the data > must be copied into the array each time. > > For an idea of the speed difference look at the difference in execution > time between updating the screen using the two methods: > > ByteBuffer getPixelData() > > and > > public void setPixelData32(int[] pixelData) > > > If you are using these direct buffers you should allocate all the > buffers you need before doing anything. Then utilize them later however > you wish. Otherwise the performance will be much worse if a new one is > constantly created. Notice that getPixelData() only creates the buffer > once. The buffer directly has access to the data of the surface! > > -Ivan/ > > Gregor M=FCckl wrote: > >Hi, Ivan! > > > >Thanks for your help. Indeed, ByteBuffer.allocateDirect() is the right > >solution and it seems to work now. I cannot tell for sure yet as the > >gtk-based input handling is still not working properly and I therefore > > can't navigate the 3D view. > > > >However, I feel that relyinig on java.nio.ByteBuffer and derivates is a > > bit strange, especially given their somewhat peculiar design. Looking at > > the code I have now which has to copy data to newly created buffers eve= ry > > time I need to pass an array to OpenGL, I get the feeling that this > > slower than dealing directly with arrays, which are readiy available in > > my case and probably more optimizeable by the Java compiler and JVM. > > > >What was the reason for using these buffers instead of arrays? Am I > > missing something here? > > > >Regards, > >Gregor > > > >On Saturday 10 September 2005 01:37, Ivan Z. Ganza wrote: > >>Gregor, > >> > >>I had a look in the code and intact SDLSurface isn't a good example > >>because the buffer is created in the native code. Have a look at > >>ByteBufferPool instead. > >> > >>-Ivan/ > >> > >>Gregor M=FCckl wrote: > >>>Hi! > >>> > >>>I"m trying to use glGetDoublev to read back the modelview and projecti= on > >>>matrices from OpenGL. However, it looks like I'm doing something wrong > >>>with the DoubleBuffers required for that. > >>> > >>>What I'm doing basically is in this code: > >>> > >>> GlewImpl gl; > >>> private ml.math.Matrix4 modelViewMatrix; > >>> private ml.math.Matrix4 projectionMatrix; > >>> private double viewFieldOfView; > >>> private DoubleBuffer matrixBuffer; > >>> > >>> public ViewWindowSpace(Widget parent) > >>> { > >>> super(); > >>> > >>> matrixBuffer=3DDoubleBuffer.allocate(16); > >>> modelViewMatrix=3Dnew Matrix4(); > >>> projectionMatrix=3Dnew Matrix4(); > >>> > >>> currentRenderMode=3DRenderMode.Solid; > >>> > >>> initGLContext(); > >>> > >>> // snip: unrelated code > >>> > >>> addListener(new LifeCycleListener() { > >>> > >>> public void lifeCycleEvent(LifeCycleEvent e) > >>> { > >>> // TODO Auto-generated method stub > >>> if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { > >>> setupViewingAreaInitial(); > >>> } > >>> > >>> } > >>> } > >>> > >>> // snip: unrelated code > >>> } > >>> > >>> protected void setupViewingAreaInitial() > >>> { > >>> viewFieldOfView=3D45.0; > >>> > >>> glBegin(); > >>> GlewJNI.SWIG_glew_init(); > >>> gl=3Dnew GlewImpl(); > >>> int width =3D getWidth(); > >>> int height =3D getHeight(); > >>> gl.glViewport(0, 0, width, height); > >>> gl.glMatrixMode(GL.GL_PROJECTION); // select the projection > >>>matrix > >>> gl.glLoadIdentity(); // reset the > >>>projection matrix > >>> float fAspect =3D (float) width / (float) height; > >>> gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); > >>> gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelview > >>>matrix gl.glLoadIdentity(); > >>> > >>> gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); > >>> modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); > >>> gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); > >>> projectionMatrix.setFromOpenGLMatrix(matrixBuffer); > >>> > >>> glEnd(); > >>> } > >>> > >>>What this does: > >>> > >>>The constructor allocates the DoubleBuffer in question and registers an > >>>event handler to do the rest of the initialilsation once the opengl > >>>context can actually be used. When this is the case, > >>>setupViewingAreaInitial is called to perform the init of the gl contex= t. > >>>This fails with a NullPointerException in the first call to > >>>gl.glGetDoublev(). The console output for this exception is as follows: > >>> > >>>Exception in thread "main" java.lang.NullPointerException: null address > >>>returned from GetDirectBufferAddress() call. Make sure the buffer is a > >>>_direct_ buffer. > >>> at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) > >>> at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:14= 3) > >>> at > >>>ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindowS= pa > >>>ce .java:322) at > >>>ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.ja= va > >>>:2 77) at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) > >>> at org.gnu.gtk.Widget.handleRealize(Widget.java:764) > >>> at org.gnu.gtk.Widget.gtk_widget_show(Native Method) > >>> at org.gnu.gtk.Widget.show(Widget.java:119) > >>> at ml.core.State.createMainWindow(State.java:158) > >>> at ml.ML3D.<init>(ML3D.java:49) > >>> at ml.ML3D.main(ML3D.java:66) > >>> > >>>I have no clue why this happens. Do I initialize the DoubleBuffer in > >>>question badly? Is there any example that shows how it should be done? > >>>Any help would be appreciated. > >>> > >>>Regards, > >>>Gregor > >>> > >>> > >>>------------------------------------------------------- > >>>SF.Net email is Sponsored by the Better Software Conference & EXPO > >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle > >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams * > >>>Testing & QA Security * Process Improvement & Measurement * > >>>http://www.sqe.com/bsce5sf > >>>_______________________________________________ > >>>sdljava-users mailing list > >>>sdl...@li... > >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users > >> > >>------------------------------------------------------- > >>SF.Net email is Sponsored by the Better Software Conference & EXPO > >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle > >> Practices Agile & Plan-Driven Development * Managing Projects & Teams * > >> Testing & QA Security * Process Improvement & Measurement * > >> http://www.sqe.com/bsce5sf > >> _______________________________________________ > >>sdljava-users mailing list > >>sdl...@li... > >>https://lists.sourceforge.net/lists/listinfo/sdljava-users > > > >------------------------------------------------------- > >SF.Net email is Sponsored by the Better Software Conference & EXPO > >September 19-22, 2005 * San Francisco, CA * Development Lifecycle > > Practices Agile & Plan-Driven Development * Managing Projects & Teams * > > Testing & QA Security * Process Improvement & Measurement * > > http://www.sqe.com/bsce5sf > > _______________________________________________ > >sdljava-users mailing list > >sdl...@li... > >https://lists.sourceforge.net/lists/listinfo/sdljava-users > > ------------------------------------------------------- > SF.Net email is Sponsored by the Better Software Conference & EXPO > September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practic= es > Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA > Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf > _______________________________________________ > sdljava-users mailing list > sdl...@li... > https://lists.sourceforge.net/lists/listinfo/sdljava-users |
From: Ivan Z. G. <iva...@ya...> - 2005-09-11 13:47:41
|
Hi Gregor, I appreciate all feedback so don't worry. Please keep it coming. The API needs to be actually _usable_ by others. You make a good point that I did not consider. From what your saying it sounds like there should be methods provided that just copy the data since it is so small. It also seems like all OpenGL functions which are similar would want to operate in a similar fashion. The problem is I'm not sure what all the functions are which would operate on a small data set. I'm still very new to OpenGL myself. Would you give me a list of the funtions you need which should just copy the data and I will add methods which do so. Please send me back anything which can make the OpenGL layer more usable. Thanks, -Ivan/ Gregor M=FCckl wrote: >Hi! > >My problem is that I really have to allocate these direct buffers on dem= and=20 >for something like one or two opengl calls each. Furthermore, they reall= y are=20 >quite small. The biggest buffer I use that way is there to store a matri= x of=20 >4x4 doubles, that is, 128 bytes. > >Using byte buffers may be a valid approach when working on large, unifor= m=20 >amounts of data like framebuffers. But that is not the case with geometr= y=20 >data for OpenGL. Using vertex arrays is almost out of question for me si= nce=20 >the geometry data I have is very dynamic in every way. > >Well, this is not trying to be a rant. I'm just not yet convinced that t= his is=20 >the right approach. It looks like far too much overhead to me, making al= l the=20 >OpenGL functions taking (small) arrays practically useless. Maybe some=20 >benchmarking is in order to get some definitive answers, but I don't hav= e=20 >enough time for that. > >Regards, >Gregor > >On Saturday 10 September 2005 23:39, Ivan Z. Ganza wrote: > =20 > >>Hi Gregor, >> >>The direct buffers introduced with NIO are better than sliced >>bread...:-) Without them I don't think it would be possible to achiev= e >>any level of meaningfully performance. >> >>A direct buffer is mapped directly to a region of memory inside the >>JVM's memory space. When you perform operations on a direct buffer the= y >>effect the memory directly and thus and are very fast. The other optio= n >>is to copy the data each time from the JVM's memory space into the >>native code space (or visa versa). The copy method is an order of >>magnitude slower. First the new array must be allocated. Then the dat= a >>must be copied into the array each time. >> >>For an idea of the speed difference look at the difference in execution >>time between updating the screen using the two methods: >> >> ByteBuffer getPixelData() >> >>and >> >> public void setPixelData32(int[] pixelData) >> >> >>If you are using these direct buffers you should allocate all the >>buffers you need before doing anything. Then utilize them later howeve= r >>you wish. Otherwise the performance will be much worse if a new one is >>constantly created. Notice that getPixelData() only creates the buffer >>once. The buffer directly has access to the data of the surface! >> >>-Ivan/ >> >>Gregor M=FCckl wrote: >> =20 >> >>>Hi, Ivan! >>> >>>Thanks for your help. Indeed, ByteBuffer.allocateDirect() is the right >>>solution and it seems to work now. I cannot tell for sure yet as the >>>gtk-based input handling is still not working properly and I therefore >>>can't navigate the 3D view. >>> >>>However, I feel that relyinig on java.nio.ByteBuffer and derivates is = a >>>bit strange, especially given their somewhat peculiar design. Looking = at >>>the code I have now which has to copy data to newly created buffers ev= ery >>>time I need to pass an array to OpenGL, I get the feeling that this >>>slower than dealing directly with arrays, which are readiy available i= n >>>my case and probably more optimizeable by the Java compiler and JVM. >>> >>>What was the reason for using these buffers instead of arrays? Am I >>>missing something here? >>> >>>Regards, >>>Gregor >>> >>>On Saturday 10 September 2005 01:37, Ivan Z. Ganza wrote: >>> =20 >>> >>>>Gregor, >>>> >>>>I had a look in the code and intact SDLSurface isn't a good example >>>>because the buffer is created in the native code. Have a look at >>>>ByteBufferPool instead. >>>> >>>>-Ivan/ >>>> >>>>Gregor M=FCckl wrote: >>>> =20 >>>> >>>>>Hi! >>>>> >>>>>I"m trying to use glGetDoublev to read back the modelview and projec= tion >>>>>matrices from OpenGL. However, it looks like I'm doing something wro= ng >>>>>with the DoubleBuffers required for that. >>>>> >>>>>What I'm doing basically is in this code: >>>>> >>>>> GlewImpl gl; >>>>> private ml.math.Matrix4 modelViewMatrix; >>>>> private ml.math.Matrix4 projectionMatrix; >>>>> private double viewFieldOfView; >>>>> private DoubleBuffer matrixBuffer; >>>>> >>>>> public ViewWindowSpace(Widget parent) >>>>> { >>>>> super(); >>>>> >>>>> matrixBuffer=3DDoubleBuffer.allocate(16); >>>>> modelViewMatrix=3Dnew Matrix4(); >>>>> projectionMatrix=3Dnew Matrix4(); >>>>> >>>>> currentRenderMode=3DRenderMode.Solid; >>>>> >>>>> initGLContext(); >>>>> >>>>> // snip: unrelated code >>>>> >>>>> addListener(new LifeCycleListener() { >>>>> >>>>> public void lifeCycleEvent(LifeCycleEvent e) >>>>> { >>>>> // TODO Auto-generated method stub >>>>> if(e.getType()=3D=3DLifeCycleEvent.Type.REALIZE) { >>>>> setupViewingAreaInitial(); >>>>> } >>>>> >>>>> } >>>>> } >>>>> >>>>> // snip: unrelated code >>>>> } >>>>> >>>>> protected void setupViewingAreaInitial() >>>>> { >>>>> viewFieldOfView=3D45.0; >>>>> >>>>> glBegin(); >>>>> GlewJNI.SWIG_glew_init(); >>>>> gl=3Dnew GlewImpl(); >>>>> int width =3D getWidth(); >>>>> int height =3D getHeight(); >>>>> gl.glViewport(0, 0, width, height); >>>>> gl.glMatrixMode(GL.GL_PROJECTION); // select the projecti= on >>>>>matrix >>>>> gl.glLoadIdentity(); // reset the >>>>>projection matrix >>>>> float fAspect =3D (float) width / (float) height; >>>>> gl.gluPerspective(viewFieldOfView, fAspect, 0.5f, 400.0f); >>>>> gl.glMatrixMode(GL.GL_MODELVIEW); // select the modelvie= w >>>>>matrix gl.glLoadIdentity(); >>>>> >>>>> gl.glGetDoublev(GL.GL_MODELVIEW_MATRIX,matrixBuffer); >>>>> modelViewMatrix.setFromOpenGLMatrix(matrixBuffer); >>>>> gl.glGetDoublev(GL.GL_PROJECTION_MATRIX,matrixBuffer); >>>>> projectionMatrix.setFromOpenGLMatrix(matrixBuffer); >>>>> >>>>> glEnd(); >>>>> } >>>>> >>>>>What this does: >>>>> >>>>>The constructor allocates the DoubleBuffer in question and registers= an >>>>>event handler to do the rest of the initialilsation once the opengl >>>>>context can actually be used. When this is the case, >>>>>setupViewingAreaInitial is called to perform the init of the gl cont= ext. >>>>>This fails with a NullPointerException in the first call to >>>>>gl.glGetDoublev(). The console output for this exception is as follo= ws: >>>>> >>>>>Exception in thread "main" java.lang.NullPointerException: null addr= ess >>>>>returned from GetDirectBufferAddress() call. Make sure the buffer i= s a >>>>>_direct_ buffer. >>>>> at org.gljava.opengl.x.swig.GlewJNI.glGetDoublev(Native Method) >>>>> at org.gljava.opengl.impl.glew.GlewImpl.glGetDoublev(GlewImpl.java:= 143) >>>>> at >>>>>ml.ui.plugins.view.ViewWindowSpace.setupViewingAreaInitial(ViewWindo= wSpa >>>>>ce .java:322) at >>>>>ml.ui.plugins.view.ViewWindowSpace$2.lifeCycleEvent(ViewWindowSpace.= java >>>>>:2 77) at org.gnu.gtk.Widget.fireLifeCycleEvent(Widget.java:735) >>>>> at org.gnu.gtk.Widget.handleRealize(Widget.java:764) >>>>> at org.gnu.gtk.Widget.gtk_widget_show(Native Method) >>>>> at org.gnu.gtk.Widget.show(Widget.java:119) >>>>> at ml.core.State.createMainWindow(State.java:158) >>>>> at ml.ML3D.<init>(ML3D.java:49) >>>>> at ml.ML3D.main(ML3D.java:66) >>>>> >>>>>I have no clue why this happens. Do I initialize the DoubleBuffer in >>>>>question badly? Is there any example that shows how it should be don= e? >>>>>Any help would be appreciated. >>>>> >>>>>Regards, >>>>>Gregor >>>>> >>>>> >>>>>------------------------------------------------------- >>>>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>>>Practices Agile & Plan-Driven Development * Managing Projects & Team= s * >>>>>Testing & QA Security * Process Improvement & Measurement * >>>>>http://www.sqe.com/bsce5sf >>>>>_______________________________________________ >>>>>sdljava-users mailing list >>>>>sdl...@li... >>>>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>>>> =20 >>>>> >>>>------------------------------------------------------- >>>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>>Practices Agile & Plan-Driven Development * Managing Projects & Teams= * >>>>Testing & QA Security * Process Improvement & Measurement * >>>>http://www.sqe.com/bsce5sf >>>>_______________________________________________ >>>>sdljava-users mailing list >>>>sdl...@li... >>>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>>> =20 >>>> >>>------------------------------------------------------- >>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams = * >>>Testing & QA Security * Process Improvement & Measurement * >>>http://www.sqe.com/bsce5sf >>>_______________________________________________ >>>sdljava-users mailing list >>>sdl...@li... >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>> =20 >>> >>------------------------------------------------------- >>SF.Net email is Sponsored by the Better Software Conference & EXPO >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle Pract= ices >>Agile & Plan-Driven Development * Managing Projects & Teams * Testing &= QA >>Security * Process Improvement & Measurement * http://www.sqe.com/bsce5= sf >>_______________________________________________ >>sdljava-users mailing list >>sdl...@li... >>https://lists.sourceforge.net/lists/listinfo/sdljava-users >> =20 >> > > >------------------------------------------------------- >SF.Net email is Sponsored by the Better Software Conference & EXPO >September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practi= ces >Agile & Plan-Driven Development * Managing Projects & Teams * Testing & = QA >Security * Process Improvement & Measurement * http://www.sqe.com/bsce5s= f >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > =20 > |
From: Robert S. <the...@gm...> - 2005-09-13 00:26:44
|
Hi, I just want to jump into the discussion because I was one of the persons who suggested Ivan to use NIO buffers instead of Java arrays (and I have some small background about the topic from JNI and GNU Classpath coding). > The biggest buffer I use that way is there to store a matrix of > 4x4 doubles, that is, 128 bytes. Perfect. This is really the point where you can use NIO buffers. It may be look odd to you but a regular Java array is more troublesome than a NIO buffer. The buffer is an object denoting a certain memory region. Therefore you can think of it as a thin wrapper around a normal C array (or memory region that allocated with malloc/calloc). A Java array is something that lifes inside the JVM and can be implemented very differently. NIO buffers and Java arrays have very similar JNI functions to interact with them. Both have a function which returns a pointer so that you can modify the data in C-style. However the array access function explicitly states that you *may* receive the pointer to a copy of the original data (remember that Java arrays life in the JVMs heap and may be moved around because of garbage collection and memory compaction). This won't happen with NIO buffers. If you have a feeling that frequent bytebuffer instantiations would harm the performance of your application then please have a look whether you may not solve this problem in a different way (e.g. pooling buffers or the like). > Using byte buffers may be a valid approach when working on large, uniform > amounts of data like framebuffers. But that is not the case with geometry > data for OpenGL. Using vertex arrays is almost out of question for me since > the geometry data I have is very dynamic in every way. Definitely not. NIO buffers can be used wherever interaction with native machinery is involved. I once wrote a jinput plugin which uses the Linux kernel's input system to access mouse/keyboard/joypad etc (You can find the sources in the respective forums at javagaming.org). It makes heavy use of NIO buffers even for such small amounts of data (key/button/axes states) and I think it is a big win that the system's kernel can write into the memory which it shares with my Java application. > Well, this is not trying to be a rant. I'm just not yet convinced that this is > the right approach. It looks like far too much overhead to me, making all the > OpenGL functions taking (small) arrays practically useless. Well, in which way could they be implemented otherwise? At one point you will forced to create a buffer in memory (probably C). If you hand over the data in Java arrays and copy it over into a malloc'ed memory region then this would hit performance seriously (You need one copy operation and one time malloc/free in GLJava's code.) With NIO buffers the JNI implementation would simply return the buffer's pointer and call the OpenGL function. The handling of the buffer (recreate it every time or do some pooling) is up to you - the application programmer. > Maybe some > benchmarking is in order to get some definitive answers, but I don't have > enough time for that. Well I try to prove it with a bit of pseudo code. (I use pseudo code because I dont know the JNI function names by heart. They are very tedious ...) 1. With Java arrays GL.java public class GL { public native setSomethingv(int[] foo); } net_sf_GL.c: setSomethingv(jvm, jobject java_array){ jint* thevalues = JVM_get_pointer_to_java_array(java_array); // may copy int size = JVM_get_size_of_java_array(java_array); int* buffer = malloc(sizeof(int) * size); memcopy(thevalues -> buffer, size * sizeof(int)); GLsetSomething(buffer); JVM_release_access_to_java_array(java_array); } 2. With NIO buffers public class GL { public native setSomethingv(IntBuffer foo); } net_sf_GL.c: setSomethingv(jvm, jobject nio_buffer){ jint* thevalues = JVM_get_pointer_of_nio_buffer(nio_buffer); GLsetSomething(thevalues); JVM_release_access_to_java_array(java_array); } (I am broadly ignoring any type conversion oddities here.) Btw: There is a utility class in GLJava that creates direct Integer, Long, Short, Double and Float buffers in one method call (In fact every newer OpenGL binding* has these methods ...) cu Robert * JOGL, LwJGL |
From: Ivan Z. G. <iva...@ya...> - 2005-09-13 02:17:42
|
Thanks for the very detailed information :-) The helpful class is sdljava.util.BufferUtil...which Robert kindly coded. Interesting to have a look at the code inside... Please let us know if your able to make it work Gregor. -Ivan/ Robert Schuster wrote: >Hi, >I just want to jump into the discussion because I was one of the persons who >suggested Ivan to use NIO buffers instead of Java arrays (and I have some small >background about the topic from JNI and GNU Classpath coding). > > > >>The biggest buffer I use that way is there to store a matrix of >>4x4 doubles, that is, 128 bytes. >> >> >Perfect. This is really the point where you can use NIO buffers. It may be look >odd to you but a regular Java array is more troublesome than a NIO buffer. The >buffer is an object denoting a certain memory region. Therefore you can think of >it as a thin wrapper around a normal C array (or memory region that allocated >with malloc/calloc). > >A Java array is something that lifes inside the JVM and can be implemented very >differently. NIO buffers and Java arrays have very similar JNI functions to >interact with them. Both have a function which returns a pointer so that you can >modify the data in C-style. However the array access function explicitly states >that you *may* receive the pointer to a copy of the original data (remember that >Java arrays life in the JVMs heap and may be moved around because of garbage >collection and memory compaction). This won't happen with NIO buffers. > >If you have a feeling that frequent bytebuffer instantiations would harm the >performance of your application then please have a look whether you may not >solve this problem in a different way (e.g. pooling buffers or the like). > > > >>Using byte buffers may be a valid approach when working on large, uniform >>amounts of data like framebuffers. But that is not the case with geometry >>data for OpenGL. Using vertex arrays is almost out of question for me since >>the geometry data I have is very dynamic in every way. >> >> >Definitely not. NIO buffers can be used wherever interaction with native >machinery is involved. I once wrote a jinput plugin which uses the Linux >kernel's input system to access mouse/keyboard/joypad etc (You can find the >sources in the respective forums at javagaming.org). It makes heavy use of NIO >buffers even for such small amounts of data (key/button/axes states) and I think >it is a big win that the system's kernel can write into the memory which it >shares with my Java application. > > > >>Well, this is not trying to be a rant. I'm just not yet convinced that this is >>the right approach. It looks like far too much overhead to me, making all the >>OpenGL functions taking (small) arrays practically useless. >> >> >Well, in which way could they be implemented otherwise? At one point you will >forced to create a buffer in memory (probably C). If you hand over the data in >Java arrays and copy it over into a malloc'ed memory region then this would hit >performance seriously (You need one copy operation and one time malloc/free in >GLJava's code.) With NIO buffers the JNI implementation would simply return the >buffer's pointer and call the OpenGL function. The handling of the buffer >(recreate it every time or do some pooling) is up to you - the application >programmer. > > > >>Maybe some >>benchmarking is in order to get some definitive answers, but I don't have >>enough time for that. >> >> >Well I try to prove it with a bit of pseudo code. (I use pseudo code because I >dont know the JNI function names by heart. They are very tedious ...) > > >1. With Java arrays >GL.java > >public class GL { > public native setSomethingv(int[] foo); >} > >net_sf_GL.c: > >setSomethingv(jvm, jobject java_array){ > > jint* thevalues = JVM_get_pointer_to_java_array(java_array); // may copy > > int size = JVM_get_size_of_java_array(java_array); > > int* buffer = malloc(sizeof(int) * size); > > memcopy(thevalues -> buffer, size * sizeof(int)); > > GLsetSomething(buffer); > > JVM_release_access_to_java_array(java_array); >} > >2. With NIO buffers > >public class GL { > public native setSomethingv(IntBuffer foo); >} >net_sf_GL.c: > >setSomethingv(jvm, jobject nio_buffer){ > > jint* thevalues = JVM_get_pointer_of_nio_buffer(nio_buffer); > > GLsetSomething(thevalues); > > JVM_release_access_to_java_array(java_array); >} > >(I am broadly ignoring any type conversion oddities here.) > >Btw: There is a utility class in GLJava that creates direct Integer, Long, >Short, Double and Float buffers in one method call (In fact every newer OpenGL >binding* has these methods ...) > >cu >Robert > >* JOGL, LwJGL > > >------------------------------------------------------- >SF.Net email is Sponsored by the Better Software Conference & EXPO >September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices >Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA >Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > > |
From: Gregor <Gre...@gm...> - 2005-09-13 06:57:12
Attachments:
nio-benchmark.tar.gz
|
Hi! I've finally tried to benchmark java arrays and direct buffers in small buffers of the size that would typically appear in OpenGL apps. The results of the runs on my computer are: gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 1033 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 817 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 32803 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 560 gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 1034 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 776 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 34588 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 591 gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 984 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 768 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 35151 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 615 gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 1093 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 847 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 35321 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 623 gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 730 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 575 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 22455 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 438 The source code for the benchmark is included. This clearly shows that direct buffers are really only viable if you can avoid their allocation. But now the problem is that caching ByteBuffers would add considerable overhead to the results of the last measurements in both sourcecode complexity and runtime. Furthermore, caching unused data structures in Java is especially bad design and any suggestion to that end can easily be seen as a sign of bad design elsewhere. And in reality it may really not be feasible. I'm writing a 3d modelling tool which cannot apply proper rendering optimizations because the geometry may essentially be anything and change at any time to anything else. So I have to use thousands of calls to glVertex3d(v) and similar. Compared to direct buffers even the reallocated arrays don't have so much added overhead. So I strongly suggest that you implement arrays at least as an alternative interface. It's easy to overload functions in Java, so this is not a problem. The source code to the benchmark is appended. Regards, Gregor On Tuesday 13 September 2005 04:17, Ivan Z. Ganza wrote: > Thanks for the very detailed information :-) > > The helpful class is sdljava.util.BufferUtil...which Robert kindly > coded. Interesting to have a look at the code inside... > > Please let us know if your able to make it work Gregor. > > -Ivan/ > > Robert Schuster wrote: > >Hi, > >I just want to jump into the discussion because I was one of the persons > > who suggested Ivan to use NIO buffers instead of Java arrays (and I have > > some small background about the topic from JNI and GNU Classpath coding). > > > >>The biggest buffer I use that way is there to store a matrix of > >>4x4 doubles, that is, 128 bytes. > > > >Perfect. This is really the point where you can use NIO buffers. It may be > > look odd to you but a regular Java array is more troublesome than a NIO > > buffer. The buffer is an object denoting a certain memory region. > > Therefore you can think of it as a thin wrapper around a normal C array > > (or memory region that allocated with malloc/calloc). > > > >A Java array is something that lifes inside the JVM and can be implemented > > very differently. NIO buffers and Java arrays have very similar JNI > > functions to interact with them. Both have a function which returns a > > pointer so that you can modify the data in C-style. However the array > > access function explicitly states that you *may* receive the pointer to a > > copy of the original data (remember that Java arrays life in the JVMs > > heap and may be moved around because of garbage collection and memory > > compaction). This won't happen with NIO buffers. > > > >If you have a feeling that frequent bytebuffer instantiations would harm > > the performance of your application then please have a look whether you > > may not solve this problem in a different way (e.g. pooling buffers or > > the like). > > > >>Using byte buffers may be a valid approach when working on large, uniform > >>amounts of data like framebuffers. But that is not the case with geometry > >>data for OpenGL. Using vertex arrays is almost out of question for me > >> since the geometry data I have is very dynamic in every way. > > > >Definitely not. NIO buffers can be used wherever interaction with native > >machinery is involved. I once wrote a jinput plugin which uses the Linux > >kernel's input system to access mouse/keyboard/joypad etc (You can find > > the sources in the respective forums at javagaming.org). It makes heavy > > use of NIO buffers even for such small amounts of data (key/button/axes > > states) and I think it is a big win that the system's kernel can write > > into the memory which it shares with my Java application. > > > >>Well, this is not trying to be a rant. I'm just not yet convinced that > >> this is the right approach. It looks like far too much overhead to me, > >> making all the OpenGL functions taking (small) arrays practically > >> useless. > > > >Well, in which way could they be implemented otherwise? At one point you > > will forced to create a buffer in memory (probably C). If you hand over > > the data in Java arrays and copy it over into a malloc'ed memory region > > then this would hit performance seriously (You need one copy operation > > and one time malloc/free in GLJava's code.) With NIO buffers the JNI > > implementation would simply return the buffer's pointer and call the > > OpenGL function. The handling of the buffer (recreate it every time or do > > some pooling) is up to you - the application programmer. > > > >>Maybe some > >>benchmarking is in order to get some definitive answers, but I don't have > >>enough time for that. > > > >Well I try to prove it with a bit of pseudo code. (I use pseudo code > > because I dont know the JNI function names by heart. They are very > > tedious ...) > > > > > >1. With Java arrays > >GL.java > > > >public class GL { > > public native setSomethingv(int[] foo); > >} > > > >net_sf_GL.c: > > > >setSomethingv(jvm, jobject java_array){ > > > > jint* thevalues = JVM_get_pointer_to_java_array(java_array); // may > > copy > > > > int size = JVM_get_size_of_java_array(java_array); > > > > int* buffer = malloc(sizeof(int) * size); > > > > memcopy(thevalues -> buffer, size * sizeof(int)); > > > > GLsetSomething(buffer); > > > > JVM_release_access_to_java_array(java_array); > >} > > > >2. With NIO buffers > > > >public class GL { > > public native setSomethingv(IntBuffer foo); > >} > >net_sf_GL.c: > > > >setSomethingv(jvm, jobject nio_buffer){ > > > > jint* thevalues = JVM_get_pointer_of_nio_buffer(nio_buffer); > > > > GLsetSomething(thevalues); > > > > JVM_release_access_to_java_array(java_array); > >} > > > >(I am broadly ignoring any type conversion oddities here.) > > > >Btw: There is a utility class in GLJava that creates direct Integer, Long, > >Short, Double and Float buffers in one method call (In fact every newer > > OpenGL binding* has these methods ...) > > > >cu > >Robert > > > >* JOGL, LwJGL > > > > > >------------------------------------------------------- > >SF.Net email is Sponsored by the Better Software Conference & EXPO > >September 19-22, 2005 * San Francisco, CA * Development Lifecycle > > Practices Agile & Plan-Driven Development * Managing Projects & Teams * > > Testing & QA Security * Process Improvement & Measurement * > > http://www.sqe.com/bsce5sf > > _______________________________________________ > >sdljava-users mailing list > >sdl...@li... > >https://lists.sourceforge.net/lists/listinfo/sdljava-users > > ------------------------------------------------------- > SF.Net email is Sponsored by the Better Software Conference & EXPO > September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices > Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA > Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf > _______________________________________________ > sdljava-users mailing list > sdl...@li... > https://lists.sourceforge.net/lists/listinfo/sdljava-users |
From: Robert S. <the...@gm...> - 2005-09-13 22:26:16
|
Hi Gregor, this is an impressive nice benchmark. Look what our free VMs can achieve: rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=. gij Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 2705 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 2242 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 4329 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 1047 (This is GCJ 4.0 somewhat.) rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=. jamvm Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 1825 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 1443 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 7916 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 278 rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ (Both are interpreted only. JamVM has a handcrafted JNI implementation that really outperforms the JDK) As a comparison my JDK 1.5.0 results: LD_LIBRARY_PATH=. /opt/sun-jdk-1.5.0/bin/java Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times result: 484 running Test Benchmark$TestArrayAllocateOnce for 1000000 times result: 386 running Test Benchmark$TestByteBufferReallocate for 1000000 times result: 15891 running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times result: 287 However your point seems to be valid. Frequent allocations of direct buffers kill performance. In my opinion this is very sad for Java because it means if (amountOfData < someMagicValue) { GL.glVertex3fv(new int[] { foo, baz, bar, ... }); } else { IntBuffer b = BufferUtils.createBuffer(...); b.put(...); GL.glVertex3fv(b); } Gregor would you mind giving your benchmark a GPL or GPL-compatible license so I may be allowed to put it into mauve (the free test suite)? I am sure Robert Lougher (JamVM) and the GCJ team is pretty interested about these results. Oh yes and you're right. For maximum control over performance GLJava should provide OpenGL's v-functions with Java arrays exactly in the way you did it in the benchmark. And then the Javadoc should mention when to use which version ... cu Robert Gregor Mückl wrote: > Hi! > > I've finally tried to benchmark java arrays and direct buffers in small > buffers of the size that would typically appear in OpenGL apps. The results > of the runs on my computer are: > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1033 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 817 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 32803 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 560 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1034 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 776 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 34588 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 591 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 984 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 768 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 35151 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 615 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1093 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 847 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 35321 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 623 > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=. java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 730 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 575 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 22455 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 438 > > The source code for the benchmark is included. This clearly shows that direct > buffers are really only viable if you can avoid their allocation. But now the > problem is that caching ByteBuffers would add considerable overhead to the > results of the last measurements in both sourcecode complexity and runtime. > Furthermore, caching unused data structures in Java is especially bad design > and any suggestion to that end can easily be seen as a sign of bad design > elsewhere. And in reality it may really not be feasible. I'm writing a 3d > modelling tool which cannot apply proper rendering optimizations because the > geometry may essentially be anything and change at any time to anything else. > So I have to use thousands of calls to glVertex3d(v) and similar. > > Compared to direct buffers even the reallocated arrays don't have so much > added overhead. So I strongly suggest that you implement arrays at least as > an alternative interface. It's easy to overload functions in Java, so this is > not a problem. > > The source code to the benchmark is appended. > > Regards, > Gregor > > On Tuesday 13 September 2005 04:17, Ivan Z. Ganza wrote: > >>Thanks for the very detailed information :-) >> >>The helpful class is sdljava.util.BufferUtil...which Robert kindly >>coded. Interesting to have a look at the code inside... >> >>Please let us know if your able to make it work Gregor. >> >>-Ivan/ >> >>Robert Schuster wrote: >> >>>Hi, >>>I just want to jump into the discussion because I was one of the persons >>>who suggested Ivan to use NIO buffers instead of Java arrays (and I have >>>some small background about the topic from JNI and GNU Classpath coding). >>> >>> >>>>The biggest buffer I use that way is there to store a matrix of >>>>4x4 doubles, that is, 128 bytes. >>> >>>Perfect. This is really the point where you can use NIO buffers. It may be >>>look odd to you but a regular Java array is more troublesome than a NIO >>>buffer. The buffer is an object denoting a certain memory region. >>>Therefore you can think of it as a thin wrapper around a normal C array >>>(or memory region that allocated with malloc/calloc). >>> >>>A Java array is something that lifes inside the JVM and can be implemented >>>very differently. NIO buffers and Java arrays have very similar JNI >>>functions to interact with them. Both have a function which returns a >>>pointer so that you can modify the data in C-style. However the array >>>access function explicitly states that you *may* receive the pointer to a >>>copy of the original data (remember that Java arrays life in the JVMs >>>heap and may be moved around because of garbage collection and memory >>>compaction). This won't happen with NIO buffers. >>> >>>If you have a feeling that frequent bytebuffer instantiations would harm >>>the performance of your application then please have a look whether you >>>may not solve this problem in a different way (e.g. pooling buffers or >>>the like). >>> >>> >>>>Using byte buffers may be a valid approach when working on large, uniform >>>>amounts of data like framebuffers. But that is not the case with geometry >>>>data for OpenGL. Using vertex arrays is almost out of question for me >>>>since the geometry data I have is very dynamic in every way. >>> >>>Definitely not. NIO buffers can be used wherever interaction with native >>>machinery is involved. I once wrote a jinput plugin which uses the Linux >>>kernel's input system to access mouse/keyboard/joypad etc (You can find >>>the sources in the respective forums at javagaming.org). It makes heavy >>>use of NIO buffers even for such small amounts of data (key/button/axes >>>states) and I think it is a big win that the system's kernel can write >>>into the memory which it shares with my Java application. >>> >>> >>>>Well, this is not trying to be a rant. I'm just not yet convinced that >>>>this is the right approach. It looks like far too much overhead to me, >>>>making all the OpenGL functions taking (small) arrays practically >>>>useless. >>> >>>Well, in which way could they be implemented otherwise? At one point you >>>will forced to create a buffer in memory (probably C). If you hand over >>>the data in Java arrays and copy it over into a malloc'ed memory region >>>then this would hit performance seriously (You need one copy operation >>>and one time malloc/free in GLJava's code.) With NIO buffers the JNI >>>implementation would simply return the buffer's pointer and call the >>>OpenGL function. The handling of the buffer (recreate it every time or do >>>some pooling) is up to you - the application programmer. >>> >>> >>>>Maybe some >>>>benchmarking is in order to get some definitive answers, but I don't have >>>>enough time for that. >>> >>>Well I try to prove it with a bit of pseudo code. (I use pseudo code >>>because I dont know the JNI function names by heart. They are very >>>tedious ...) >>> >>> >>>1. With Java arrays >>>GL.java >>> >>>public class GL { >>> public native setSomethingv(int[] foo); >>>} >>> >>>net_sf_GL.c: >>> >>>setSomethingv(jvm, jobject java_array){ >>> >>> jint* thevalues = JVM_get_pointer_to_java_array(java_array); // may >>>copy >>> >>> int size = JVM_get_size_of_java_array(java_array); >>> >>> int* buffer = malloc(sizeof(int) * size); >>> >>> memcopy(thevalues -> buffer, size * sizeof(int)); >>> >>> GLsetSomething(buffer); >>> >>> JVM_release_access_to_java_array(java_array); >>>} >>> >>>2. With NIO buffers >>> >>>public class GL { >>> public native setSomethingv(IntBuffer foo); >>>} >>>net_sf_GL.c: >>> >>>setSomethingv(jvm, jobject nio_buffer){ >>> >>> jint* thevalues = JVM_get_pointer_of_nio_buffer(nio_buffer); >>> >>> GLsetSomething(thevalues); >>> >>> JVM_release_access_to_java_array(java_array); >>>} >>> >>>(I am broadly ignoring any type conversion oddities here.) >>> >>>Btw: There is a utility class in GLJava that creates direct Integer, Long, >>>Short, Double and Float buffers in one method call (In fact every newer >>>OpenGL binding* has these methods ...) >>> >>>cu >>>Robert >>> >>>* JOGL, LwJGL >>> >>> >>>------------------------------------------------------- >>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams * >>>Testing & QA Security * Process Improvement & Measurement * >>>http://www.sqe.com/bsce5sf >>>_______________________________________________ >>>sdljava-users mailing list >>>sdl...@li... >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >> >>------------------------------------------------------- >>SF.Net email is Sponsored by the Better Software Conference & EXPO >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle Practices >>Agile & Plan-Driven Development * Managing Projects & Teams * Testing & QA >>Security * Process Improvement & Measurement * http://www.sqe.com/bsce5sf >>_______________________________________________ >>sdljava-users mailing list >>sdl...@li... >>https://lists.sourceforge.net/lists/listinfo/sdljava-users |
From: Ivan Z. G. <iva...@ya...> - 2005-09-13 22:54:25
|
Good discussion! I will add the methods as you describe. Regarding the documentation, once the first part is done, I'll let you guys know. Please give me pointers how I can improve the docs that I do include. I'm not sure I will be able to properly document where to use one versus the other. Thanks for all the discussion and feedback! PS: I will implement glGetDoublev in this manner soon so Gregor can continue his work. The rest will come later as I will need to write a ruby script to create the actual source code for me...its way too much typing for my old fingers ... ;-) -Ivan/ Robert Schuster wrote: >Hi Gregor, >this is an impressive nice benchmark. Look what our free VMs can achieve= : > >rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=3D. gij = Benchmark >running Test Benchmark$TestArrayReallocate for 1000000 times >result: 2705 >running Test Benchmark$TestArrayAllocateOnce for 1000000 times >result: 2242 >running Test Benchmark$TestByteBufferReallocate for 1000000 times >result: 4329 >running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >result: 1047 > >(This is GCJ 4.0 somewhat.) > >rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=3D. jamv= m Benchmark >running Test Benchmark$TestArrayReallocate for 1000000 times >result: 1825 >running Test Benchmark$TestArrayAllocateOnce for 1000000 times >result: 1443 >running Test Benchmark$TestByteBufferReallocate for 1000000 times >result: 7916 >running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >result: 278 >rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ > >(Both are interpreted only. JamVM has a handcrafted JNI implementation t= hat >really outperforms the JDK) > >As a comparison my JDK 1.5.0 results: >LD_LIBRARY_PATH=3D. /opt/sun-jdk-1.5.0/bin/java Benchmark >running Test Benchmark$TestArrayReallocate for 1000000 times >result: 484 >running Test Benchmark$TestArrayAllocateOnce for 1000000 times >result: 386 >running Test Benchmark$TestByteBufferReallocate for 1000000 times >result: 15891 >running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >result: 287 > >However your point seems to be valid. Frequent allocations of direct buf= fers >kill performance. In my opinion this is very sad for Java because it mea= ns > >if (amountOfData < someMagicValue) { > GL.glVertex3fv(new int[] { foo, baz, bar, ... }); >} else { > IntBuffer b =3D BufferUtils.createBuffer(...); > b.put(...); > GL.glVertex3fv(b); >} > >Gregor would you mind giving your benchmark a GPL or GPL-compatible lice= nse so I >may be allowed to put it into mauve (the free test suite)? I am sure Rob= ert >Lougher (JamVM) and the GCJ team is pretty interested about these result= s. > >Oh yes and you're right. For maximum control over performance GLJava sho= uld >provide OpenGL's v-functions with Java arrays exactly in the way you did= it in >the benchmark. And then the Javadoc should mention when to use which ver= sion ... > >cu >Robert > >Gregor M=C3=BCckl wrote: > =20 > >>Hi! >> >>I've finally tried to benchmark java arrays and direct buffers in small= =20 >>buffers of the size that would typically appear in OpenGL apps. The res= ults=20 >>of the runs on my computer are: >> >>gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark >>running Test Benchmark$TestArrayReallocate for 1000000 times >>result: 1033 >>running Test Benchmark$TestArrayAllocateOnce for 1000000 times >>result: 817 >>running Test Benchmark$TestByteBufferReallocate for 1000000 times >>result: 32803 >>running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >>result: 560 >>gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark >>running Test Benchmark$TestArrayReallocate for 1000000 times >>result: 1034 >>running Test Benchmark$TestArrayAllocateOnce for 1000000 times >>result: 776 >>running Test Benchmark$TestByteBufferReallocate for 1000000 times >>result: 34588 >>running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >>result: 591 >>gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark >>running Test Benchmark$TestArrayReallocate for 1000000 times >>result: 984 >>running Test Benchmark$TestArrayAllocateOnce for 1000000 times >>result: 768 >>running Test Benchmark$TestByteBufferReallocate for 1000000 times >>result: 35151 >>running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >>result: 615 >>gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark >>running Test Benchmark$TestArrayReallocate for 1000000 times >>result: 1093 >>running Test Benchmark$TestArrayAllocateOnce for 1000000 times >>result: 847 >>running Test Benchmark$TestByteBufferReallocate for 1000000 times >>result: 35321 >>running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >>result: 623 >>gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark >>running Test Benchmark$TestArrayReallocate for 1000000 times >>result: 730 >>running Test Benchmark$TestArrayAllocateOnce for 1000000 times >>result: 575 >>running Test Benchmark$TestByteBufferReallocate for 1000000 times >>result: 22455 >>running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times >>result: 438 >> >>The source code for the benchmark is included. This clearly shows that = direct=20 >>buffers are really only viable if you can avoid their allocation. But n= ow the=20 >>problem is that caching ByteBuffers would add considerable overhead to = the=20 >>results of the last measurements in both sourcecode complexity and runt= ime.=20 >>Furthermore, caching unused data structures in Java is especially bad d= esign=20 >>and any suggestion to that end can easily be seen as a sign of bad desi= gn=20 >>elsewhere. And in reality it may really not be feasible. I'm writing a = 3d=20 >>modelling tool which cannot apply proper rendering optimizations becaus= e the=20 >>geometry may essentially be anything and change at any time to anything= else.=20 >>So I have to use thousands of calls to glVertex3d(v) and similar. >> >>Compared to direct buffers even the reallocated arrays don't have so mu= ch=20 >>added overhead. So I strongly suggest that you implement arrays at leas= t as=20 >>an alternative interface. It's easy to overload functions in Java, so t= his is=20 >>not a problem. >> >>The source code to the benchmark is appended. >> >>Regards, >>Gregor >> >>On Tuesday 13 September 2005 04:17, Ivan Z. Ganza wrote: >> >> =20 >> >>>Thanks for the very detailed information :-) >>> >>>The helpful class is sdljava.util.BufferUtil...which Robert kindly >>>coded. Interesting to have a look at the code inside... >>> >>>Please let us know if your able to make it work Gregor. >>> >>>-Ivan/ >>> >>>Robert Schuster wrote: >>> >>> =20 >>> >>>>Hi, >>>>I just want to jump into the discussion because I was one of the pers= ons >>>>who suggested Ivan to use NIO buffers instead of Java arrays (and I h= ave >>>>some small background about the topic from JNI and GNU Classpath codi= ng). >>>> >>>> >>>> =20 >>>> >>>>>The biggest buffer I use that way is there to store a matrix of >>>>>4x4 doubles, that is, 128 bytes. >>>>> =20 >>>>> >>>>Perfect. This is really the point where you can use NIO buffers. It m= ay be >>>>look odd to you but a regular Java array is more troublesome than a N= IO >>>>buffer. The buffer is an object denoting a certain memory region. >>>>Therefore you can think of it as a thin wrapper around a normal C arr= ay >>>>(or memory region that allocated with malloc/calloc). >>>> >>>>A Java array is something that lifes inside the JVM and can be implem= ented >>>>very differently. NIO buffers and Java arrays have very similar JNI >>>>functions to interact with them. Both have a function which returns a >>>>pointer so that you can modify the data in C-style. However the array >>>>access function explicitly states that you *may* receive the pointer = to a >>>>copy of the original data (remember that Java arrays life in the JVMs >>>>heap and may be moved around because of garbage collection and memory >>>>compaction). This won't happen with NIO buffers. >>>> >>>>If you have a feeling that frequent bytebuffer instantiations would h= arm >>>>the performance of your application then please have a look whether y= ou >>>>may not solve this problem in a different way (e.g. pooling buffers o= r >>>>the like). >>>> >>>> >>>> =20 >>>> >>>>>Using byte buffers may be a valid approach when working on large, un= iform >>>>>amounts of data like framebuffers. But that is not the case with geo= metry >>>>>data for OpenGL. Using vertex arrays is almost out of question for m= e >>>>>since the geometry data I have is very dynamic in every way. >>>>> =20 >>>>> >>>>Definitely not. NIO buffers can be used wherever interaction with nat= ive >>>>machinery is involved. I once wrote a jinput plugin which uses the Li= nux >>>>kernel's input system to access mouse/keyboard/joypad etc (You can fi= nd >>>>the sources in the respective forums at javagaming.org). It makes hea= vy >>>>use of NIO buffers even for such small amounts of data (key/button/ax= es >>>>states) and I think it is a big win that the system's kernel can writ= e >>>>into the memory which it shares with my Java application. >>>> >>>> >>>> =20 >>>> >>>>>Well, this is not trying to be a rant. I'm just not yet convinced th= at >>>>>this is the right approach. It looks like far too much overhead to m= e, >>>>>making all the OpenGL functions taking (small) arrays practically >>>>>useless. >>>>> =20 >>>>> >>>>Well, in which way could they be implemented otherwise? At one point = you >>>>will forced to create a buffer in memory (probably C). If you hand ov= er >>>>the data in Java arrays and copy it over into a malloc'ed memory regi= on >>>>then this would hit performance seriously (You need one copy operatio= n >>>>and one time malloc/free in GLJava's code.) With NIO buffers the JNI >>>>implementation would simply return the buffer's pointer and call the >>>>OpenGL function. The handling of the buffer (recreate it every time o= r do >>>>some pooling) is up to you - the application programmer. >>>> >>>> >>>> =20 >>>> >>>>>Maybe some >>>>>benchmarking is in order to get some definitive answers, but I don't= have >>>>>enough time for that. >>>>> =20 >>>>> >>>>Well I try to prove it with a bit of pseudo code. (I use pseudo code >>>>because I dont know the JNI function names by heart. They are very >>>>tedious ...) >>>> >>>> >>>>1. With Java arrays >>>>GL.java >>>> >>>>public class GL { >>>>public native setSomethingv(int[] foo); >>>>} >>>> >>>>net_sf_GL.c: >>>> >>>>setSomethingv(jvm, jobject java_array){ >>>> >>>> jint* thevalues =3D JVM_get_pointer_to_java_array(java_array); // ma= y >>>>copy >>>> >>>> int size =3D JVM_get_size_of_java_array(java_array); >>>> >>>> int* buffer =3D malloc(sizeof(int) * size); >>>> >>>> memcopy(thevalues -> buffer, size * sizeof(int)); >>>> >>>> GLsetSomething(buffer); >>>> >>>> JVM_release_access_to_java_array(java_array); >>>>} >>>> >>>>2. With NIO buffers >>>> >>>>public class GL { >>>>public native setSomethingv(IntBuffer foo); >>>>} >>>>net_sf_GL.c: >>>> >>>>setSomethingv(jvm, jobject nio_buffer){ >>>> >>>> jint* thevalues =3D JVM_get_pointer_of_nio_buffer(nio_buffer); >>>> >>>> GLsetSomething(thevalues); >>>> >>>> JVM_release_access_to_java_array(java_array); >>>>} >>>> >>>>(I am broadly ignoring any type conversion oddities here.) >>>> >>>>Btw: There is a utility class in GLJava that creates direct Integer, = Long, >>>>Short, Double and Float buffers in one method call (In fact every new= er >>>>OpenGL binding* has these methods ...) >>>> >>>>cu >>>>Robert >>>> >>>>* JOGL, LwJGL >>>> >>>> >>>>------------------------------------------------------- >>>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle >>>>Practices Agile & Plan-Driven Development * Managing Projects & Teams= * >>>>Testing & QA Security * Process Improvement & Measurement * >>>>http://www.sqe.com/bsce5sf >>>>_______________________________________________ >>>>sdljava-users mailing list >>>>sdl...@li... >>>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>>> =20 >>>> >>>------------------------------------------------------- >>>SF.Net email is Sponsored by the Better Software Conference & EXPO >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle Prac= tices >>>Agile & Plan-Driven Development * Managing Projects & Teams * Testing = & QA >>>Security * Process Improvement & Measurement * http://www.sqe.com/bsce= 5sf >>>_______________________________________________ >>>sdljava-users mailing list >>>sdl...@li... >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users >>> =20 >>> > > >------------------------------------------------------- >SF.Net email is sponsored by: >Tame your development challenges with Apache's Geronimo App Server. Down= load >it for free - -and be entered to win a 42" plasma tv or your very own >Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php >_______________________________________________ >sdljava-users mailing list >sdl...@li... >https://lists.sourceforge.net/lists/listinfo/sdljava-users > =20 > |
From: Gregor <Gre...@gm...> - 2005-09-13 23:44:33
|
Your numbers are pretty impressive. May I ask what CPU you used for these?= =20 I've tested with the Sun J2SDK 1.5.0.04 on an Athlon XP 1800+ with 1GB main= =20 memory, in case that matters. I forgot to mention that in my original email= =2E=20 Sorry about that. And I really need a compiler/VM combo that can deal with= =20 generics as my code is littered with uses of the new java.util generics. I= =20 don't know if jamvm or gcj are there yet. There seems to be a minor misunderstanding about glVertex3d and similar: th= e=20 size of the expected data array is fixed. For example glVertex3f expects 3= =20 floats and glVertex2d expects 2 doubles, etc... So for the majority of thes= e=20 functions you really only pass fixed small amounts of data. And about the benchmark: I wrote and ran that in about half a hour this=20 morning and there's no need to overly copyright such little amount of work = as=20 that actually was. So give it whatever license you might see fit. I'm fine= =20 with the GPL in particular if you add the right headers for me :-). Ivan: Thanks for these changes. And I fully understand the need for scripts= to=20 generate the source code. The number of functions following the same patter= n=20 in OpenGL is insane and anyone not autogenerating the bindings for them wou= ld=20 be a fool. Thanks for your support to both of you! Regards, Gregor On Wednesday 14 September 2005 00:32, Robert Schuster wrote: > Hi Gregor, > this is an impressive nice benchmark. Look what our free VMs can achieve: > > rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=3D. gij > Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times > result: 2705 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 2242 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 4329 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 1047 > > (This is GCJ 4.0 somewhat.) > > rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ LD_LIBRARY_PATH=3D. jamvm > Benchmark running Test Benchmark$TestArrayReallocate for 1000000 times > result: 1825 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 1443 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 7916 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 278 > rob@linkist ~/tmp/test/bench/buffer-vs-arrays $ > > (Both are interpreted only. JamVM has a handcrafted JNI implementation th= at > really outperforms the JDK) > > As a comparison my JDK 1.5.0 results: > LD_LIBRARY_PATH=3D. /opt/sun-jdk-1.5.0/bin/java Benchmark > running Test Benchmark$TestArrayReallocate for 1000000 times > result: 484 > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > result: 386 > running Test Benchmark$TestByteBufferReallocate for 1000000 times > result: 15891 > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > result: 287 > > However your point seems to be valid. Frequent allocations of direct > buffers kill performance. In my opinion this is very sad for Java because > it means > > if (amountOfData < someMagicValue) { > GL.glVertex3fv(new int[] { foo, baz, bar, ... }); > } else { > IntBuffer b =3D BufferUtils.createBuffer(...); > b.put(...); > GL.glVertex3fv(b); > } > > Gregor would you mind giving your benchmark a GPL or GPL-compatible licen= se > so I may be allowed to put it into mauve (the free test suite)? I am sure > Robert Lougher (JamVM) and the GCJ team is pretty interested about these > results. > > Oh yes and you're right. For maximum control over performance GLJava shou= ld > provide OpenGL's v-functions with Java arrays exactly in the way you did = it > in the benchmark. And then the Javadoc should mention when to use which > version ... > > cu > Robert > > Gregor M=C3=BCckl wrote: > > Hi! > > > > I've finally tried to benchmark java arrays and direct buffers in small > > buffers of the size that would typically appear in OpenGL apps. The > > results of the runs on my computer are: > > > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark > > running Test Benchmark$TestArrayReallocate for 1000000 times > > result: 1033 > > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > > result: 817 > > running Test Benchmark$TestByteBufferReallocate for 1000000 times > > result: 32803 > > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > > result: 560 > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark > > running Test Benchmark$TestArrayReallocate for 1000000 times > > result: 1034 > > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > > result: 776 > > running Test Benchmark$TestByteBufferReallocate for 1000000 times > > result: 34588 > > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > > result: 591 > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark > > running Test Benchmark$TestArrayReallocate for 1000000 times > > result: 984 > > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > > result: 768 > > running Test Benchmark$TestByteBufferReallocate for 1000000 times > > result: 35151 > > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > > result: 615 > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark > > running Test Benchmark$TestArrayReallocate for 1000000 times > > result: 1093 > > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > > result: 847 > > running Test Benchmark$TestByteBufferReallocate for 1000000 times > > result: 35321 > > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > > result: 623 > > gregor@goose ~/progs/nio-benchmark $ LD_LIBRARY_PATH=3D. java Benchmark > > running Test Benchmark$TestArrayReallocate for 1000000 times > > result: 730 > > running Test Benchmark$TestArrayAllocateOnce for 1000000 times > > result: 575 > > running Test Benchmark$TestByteBufferReallocate for 1000000 times > > result: 22455 > > running Test Benchmark$TestByteBufferAllocateOnce for 1000000 times > > result: 438 > > > > The source code for the benchmark is included. This clearly shows that > > direct buffers are really only viable if you can avoid their allocation. > > But now the problem is that caching ByteBuffers would add considerable > > overhead to the results of the last measurements in both sourcecode > > complexity and runtime. Furthermore, caching unused data structures in > > Java is especially bad design and any suggestion to that end can easily > > be seen as a sign of bad design elsewhere. And in reality it may really > > not be feasible. I'm writing a 3d modelling tool which cannot apply > > proper rendering optimizations because the geometry may essentially be > > anything and change at any time to anything else. So I have to use > > thousands of calls to glVertex3d(v) and similar. > > > > Compared to direct buffers even the reallocated arrays don't have so mu= ch > > added overhead. So I strongly suggest that you implement arrays at least > > as an alternative interface. It's easy to overload functions in Java, so > > this is not a problem. > > > > The source code to the benchmark is appended. > > > > Regards, > > Gregor > > > > On Tuesday 13 September 2005 04:17, Ivan Z. Ganza wrote: > >>Thanks for the very detailed information :-) > >> > >>The helpful class is sdljava.util.BufferUtil...which Robert kindly > >>coded. Interesting to have a look at the code inside... > >> > >>Please let us know if your able to make it work Gregor. > >> > >>-Ivan/ > >> > >>Robert Schuster wrote: > >>>Hi, > >>>I just want to jump into the discussion because I was one of the perso= ns > >>>who suggested Ivan to use NIO buffers instead of Java arrays (and I ha= ve > >>>some small background about the topic from JNI and GNU Classpath > >>> coding). > >>> > >>>>The biggest buffer I use that way is there to store a matrix of > >>>>4x4 doubles, that is, 128 bytes. > >>> > >>>Perfect. This is really the point where you can use NIO buffers. It may > >>> be look odd to you but a regular Java array is more troublesome than a > >>> NIO buffer. The buffer is an object denoting a certain memory region. > >>> Therefore you can think of it as a thin wrapper around a normal C arr= ay > >>> (or memory region that allocated with malloc/calloc). > >>> > >>>A Java array is something that lifes inside the JVM and can be > >>> implemented very differently. NIO buffers and Java arrays have very > >>> similar JNI functions to interact with them. Both have a function whi= ch > >>> returns a pointer so that you can modify the data in C-style. However > >>> the array access function explicitly states that you *may* receive the > >>> pointer to a copy of the original data (remember that Java arrays life > >>> in the JVMs heap and may be moved around because of garbage collection > >>> and memory compaction). This won't happen with NIO buffers. > >>> > >>>If you have a feeling that frequent bytebuffer instantiations would ha= rm > >>>the performance of your application then please have a look whether you > >>>may not solve this problem in a different way (e.g. pooling buffers or > >>>the like). > >>> > >>>>Using byte buffers may be a valid approach when working on large, > >>>> uniform amounts of data like framebuffers. But that is not the case > >>>> with geometry data for OpenGL. Using vertex arrays is almost out of > >>>> question for me since the geometry data I have is very dynamic in > >>>> every way. > >>> > >>>Definitely not. NIO buffers can be used wherever interaction with nati= ve > >>>machinery is involved. I once wrote a jinput plugin which uses the Lin= ux > >>>kernel's input system to access mouse/keyboard/joypad etc (You can find > >>>the sources in the respective forums at javagaming.org). It makes heavy > >>>use of NIO buffers even for such small amounts of data (key/button/axes > >>>states) and I think it is a big win that the system's kernel can write > >>>into the memory which it shares with my Java application. > >>> > >>>>Well, this is not trying to be a rant. I'm just not yet convinced that > >>>>this is the right approach. It looks like far too much overhead to me, > >>>>making all the OpenGL functions taking (small) arrays practically > >>>>useless. > >>> > >>>Well, in which way could they be implemented otherwise? At one point y= ou > >>>will forced to create a buffer in memory (probably C). If you hand over > >>>the data in Java arrays and copy it over into a malloc'ed memory region > >>>then this would hit performance seriously (You need one copy operation > >>>and one time malloc/free in GLJava's code.) With NIO buffers the JNI > >>>implementation would simply return the buffer's pointer and call the > >>>OpenGL function. The handling of the buffer (recreate it every time or > >>> do some pooling) is up to you - the application programmer. > >>> > >>>>Maybe some > >>>>benchmarking is in order to get some definitive answers, but I don't > >>>> have enough time for that. > >>> > >>>Well I try to prove it with a bit of pseudo code. (I use pseudo code > >>>because I dont know the JNI function names by heart. They are very > >>>tedious ...) > >>> > >>> > >>>1. With Java arrays > >>>GL.java > >>> > >>>public class GL { > >>> public native setSomethingv(int[] foo); > >>>} > >>> > >>>net_sf_GL.c: > >>> > >>>setSomethingv(jvm, jobject java_array){ > >>> > >>> jint* thevalues =3D JVM_get_pointer_to_java_array(java_array); // may > >>>copy > >>> > >>> int size =3D JVM_get_size_of_java_array(java_array); > >>> > >>> int* buffer =3D malloc(sizeof(int) * size); > >>> > >>> memcopy(thevalues -> buffer, size * sizeof(int)); > >>> > >>> GLsetSomething(buffer); > >>> > >>> JVM_release_access_to_java_array(java_array); > >>>} > >>> > >>>2. With NIO buffers > >>> > >>>public class GL { > >>> public native setSomethingv(IntBuffer foo); > >>>} > >>>net_sf_GL.c: > >>> > >>>setSomethingv(jvm, jobject nio_buffer){ > >>> > >>> jint* thevalues =3D JVM_get_pointer_of_nio_buffer(nio_buffer); > >>> > >>> GLsetSomething(thevalues); > >>> > >>> JVM_release_access_to_java_array(java_array); > >>>} > >>> > >>>(I am broadly ignoring any type conversion oddities here.) > >>> > >>>Btw: There is a utility class in GLJava that creates direct Integer, > >>> Long, Short, Double and Float buffers in one method call (In fact eve= ry > >>> newer OpenGL binding* has these methods ...) > >>> > >>>cu > >>>Robert > >>> > >>>* JOGL, LwJGL > >>> > >>> > >>>------------------------------------------------------- > >>>SF.Net email is Sponsored by the Better Software Conference & EXPO > >>>September 19-22, 2005 * San Francisco, CA * Development Lifecycle > >>>Practices Agile & Plan-Driven Development * Managing Projects & Teams * > >>>Testing & QA Security * Process Improvement & Measurement * > >>>http://www.sqe.com/bsce5sf > >>>_______________________________________________ > >>>sdljava-users mailing list > >>>sdl...@li... > >>>https://lists.sourceforge.net/lists/listinfo/sdljava-users > >> > >>------------------------------------------------------- > >>SF.Net email is Sponsored by the Better Software Conference & EXPO > >>September 19-22, 2005 * San Francisco, CA * Development Lifecycle > >> Practices Agile & Plan-Driven Development * Managing Projects & Teams * > >> Testing & QA Security * Process Improvement & Measurement * > >> http://www.sqe.com/bsce5sf > >> _______________________________________________ > >>sdljava-users mailing list > >>sdl...@li... > >>https://lists.sourceforge.net/lists/listinfo/sdljava-users > > ------------------------------------------------------- > SF.Net email is sponsored by: > Tame your development challenges with Apache's Geronimo App Server. > Download it for free - -and be entered to win a 42" plasma tv or your very > own Sony(tm)PSP. Click here to play: http://sourceforge.net/geronimo.php > _______________________________________________ > sdljava-users mailing list > sdl...@li... > https://lists.sourceforge.net/lists/listinfo/sdljava-users |