Let me explain something.  Using directly allocated NIO buffers is a
DIRECT LINK between Java and native.  The pointer you get from (void
*)GetDirectBufferAddress points to the exact memory that the Java
buffer is using.  The memory is not managed in Java on the heap like
everything else.  This is one of the few cases where you can write to
natively accessible code that does not need to be copied to work on
like an array does.

It's not a copy.  It's the original buffer data that the native side
sees.  That memory will be freed when the Buffer's java object is GCed
(from no more references.)  It's safe to use that address so long as
you're still holding on to a reference to the Buffer (in Java, not
native.  That native pointer is only as good as the java
counterpart).  In the context of OpenGL, the memory is needed during
the GL bufferdata or GL array call and most likely during the draw
call (As that normally needs to read from system memory, particularly
with arrays) but I don't know if it needs it all the way to the end of
the flush.  One would have to ask why you'd be allocating/deallocating
memory in a real time simulation, though :)  Preallocation throughout
the sim would be the ideal solution and that wouldn't have issues with
invalidating memory before it's done being used.

Like Bob said, don't be creating new buffers all the time.  In a
dynamic system (where you don't know how many triangles you'll be
drawing until visibility checks are done), make one the biggest buffer
it ever needs to be and use however much of it you need to use for
that draw.  Most systems are relatively static, though, so all you
need to do is preallocate for each unique 3d object and use transforms
to do the dirty work.

I have a dynamic system for animations so I end up recalcing vertex
positions, but that's a fixed size buffer so I never need to
reallocate.  I just process it in native code and it really works
great.

On Feb 25, 11:30 am, Bob Kerns <[email protected]> wrote:
> This would be a bug in the JNI code, which is responsible for
> protecting from the GC any and all memory which it is using. Only it
> can do so, because only it knows when it is done.
>
> That's unlikely, though. The the JNI API makes it impossible to get
> your JNI code to get its hands on the data without protecting it from
> the GC -- and even then, you may only get a copy, if the system feels
> like doing that instead. Bugs ARE still possible -- you can free it an
> then hang onto the data you no longer have rights to.
>
> But really, the only impact of holding onto a buffer on the Java side,
> only to discard it next frame, is to make the GC work harder.  If you
> were to REUSE that buffer, however, you'd avoiding extra GC work.
>
> On Feb 25, 12:45 am, Twisted Ware <[email protected]> wrote:
>
>
>
> > Robert has a very good point, but I also think you can expect the GL
> > implementation to allow the buffers to get garbage collected before
> > they have been used.
>
> > You allocate the buffer in a scope and then pass that buffer pointer
> > into the GL system - and then toss the memory away. Unless you flush
> > the GL queue, there is no guarantee the graphics system has done
> > anything with the data you've passed. The point of the direct buffers
> > is to prevent copying data around all the time during these calls, so
> > the GL system could be using the memory directly much later than you
> > expect. You should probably not deallocate the buffer until the next
> > frame comes around, when you know the system is done with the data.
>
> > On Feb 24, 2:50 pm, Robert Green <[email protected]> wrote:
>
> > > The OpenGL wrappers take the data pointer passed in by those sorts of
> > > methods using native GetDirectBufferAddress of the corresponding type
> > > (int or float) and pass that pointer into the native gl method.  That
> > > only works correctly if it's a direct buffer.
>
> > > I just checked android_opengl_GLES10.cpp and GLES11.cpp and found that
> > > glTexImage2D and glBufferData use the same getPointer() method to get
> > > to the data.  That means that behavior should be the same.
> > > Ultimately, the data comes from:
>
> > > *array = (jarray) _env->CallStaticObjectMethod(nioAccessClass,
> > >             getBaseArrayID, buffer);
> > >     offset = _env->CallStaticIntMethod(nioAccessClass,
> > >             getBaseArrayOffsetID, buffer);
> > >     data = _env->GetPrimitiveArrayCritical(*array, (jboolean *)
> > > 0);
> > >     return (void *) ((char *) data + offset);
>
> > > then the gl method is called, then the pointer is released.
>
> > > Always use direct buffers when working with any aspect of OpenGL on
> > > Android.
>
> > > On Feb 24, 4:01 am, Clankrieger <[email protected]> wrote:
>
> > > > As what I am aware of, VBOs do not need direct buffers (and indirect
> > > > buffers might be handled faster), but this is just a detail. I also
> > > > tried GL_FIXED but it did not make much difference for me. I assume
> > > > that it gives performance gains only if you have a) static data that
> > > > is converted to fixed format once and then re-rendered or b) do all
> > > > calculations with fixed number precision (which is making things a lot
> > > > more complicated and less readable when you need to update data). So I
> > > > switched back to Float because I hat to convert most values to fixed
> > > > before uploading them in GL calls.
>
> > > > I wonder if your offsets are correct? Is _pos_size_bytes the correct
> > > > offset? For safety, I would stick to non-interleaved arrays for
> > > > testing. Also I'm not sure when to array-copying in the bufferdata
> > > > call takes place - have you tried a glFlush call or a buffer rebind
> > > > (bind VBO to 0 and the ID again) after all the buffering? Somebody
> > > > with knowledge about the native part of of this buffering could help
> > > > you better with this, I guess.
>
> > > > T.
>
> > > > On Feb 16, 8:43 pm, Viktor Linder <[email protected]> wrote:
>
> > > > > As you say, the most likely explanation is that I have a bad pointer
> > > > > being used somewhere. The thing is I have gone over this code a bunch
> > > > > of times and tried lots of different checks and I just can't find
> > > > > what's wrong.
> > > > > Do you have any pointers on ways to debug the crash in the GL library?
>
> > > > > I forgot to mention: I bind the array buffer to 0 after the call to
> > > > > glDrawElements(), so any future draw calls that are not using VBOs
> > > > > will not break. Also, I am not using VBOs for all draw calls.
>
> > > > > You keep a different VBO for each channel; is using a single VBO for
> > > > > several channels not allowed?
>
> > > > > If its possible to use a single buffer that would reduce the needed
> > > > > calls to glBindBuffer() and allowed interleaved data which would
> > > > > improve cache locality.
>
> > > > > Curious; did using GL_FIXED give a large performance gain?
>
> > > > > Thanks for your help.
>
> > > > > /Viktor
> > > > > On 16 Feb, 21:25, Robert Green <[email protected]> wrote:
>
> > > > > > You're probably pointing something to some bad memory location
> > > > > > somewhere.  I know you didn't post all of your real code so I can't
> > > > > > really say for sure but it looks to me like you may be doing 
> > > > > > something
> > > > > > wrong with your buffers.  Here's how I do it:
>
> > > > > > -- Load --
> > > > > >                         GL11 gl11 = (GL11) gl;
> > > > > >                         if (modelData.normals != null) {
> > > > > >                                 int[] vboIds = new int[5];
> > > > > >                                 gl11.glGenBuffers(5, vboIds, 0);
> > > > > >                                 vertexVBOId = vboIds[0];
> > > > > >                                 texVBOId = vboIds[1];
> > > > > >                                 normalVBOId = vboIds[2];
> > > > > >                                 indexVBOId = vboIds[3];
> > > > > >                                 lightmapVBOId = vboIds[4];
> > > > > >                         } else {
> > > > > >                                 int[] vboIds = new int[4];
> > > > > >                                 gl11.glGenBuffers(4, vboIds, 0);
> > > > > >                                 vertexVBOId = vboIds[0];
> > > > > >                                 texVBOId = vboIds[1];
> > > > > >                                 indexVBOId = vboIds[2];
> > > > > >                                 lightmapVBOId = vboIds[3];
> > > > > >                         }
> > > > > >                         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 
> > > > > > vertexVBOId);
> > > > > >                         gl11.glBufferData(GL11.GL_ARRAY_BUFFER, 
> > > > > > modelData.vertices.length *
> > > > > > 4, BufferUtil.createDirectIntBuffer(modelData.vertices),
> > > > > > GL11.GL_STATIC_DRAW);
> > > > > >                         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 
> > > > > > texVBOId);
> > > > > >                         gl11.glBufferData(GL11.GL_ARRAY_BUFFER, 
> > > > > > modelData.tex.length * 4,
> > > > > > BufferUtil.createDirectIntBuffer(modelData.tex), 
> > > > > > GL11.GL_STATIC_DRAW);
> > > > > >                         if (modelData.normals != null) {
> > > > > >                                 
> > > > > > gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, normalVBOId);
> > > > > >                                 
> > > > > > gl11.glBufferData(GL11.GL_ARRAY_BUFFER, modelData.normals.length *
> > > > > > 4, BufferUtil.createDirectIntBuffer(modelData.normals),
> > > > > > GL11.GL_STATIC_DRAW);
> > > > > >                         }
> > > > > >                         
> > > > > > gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexVBOId);
> > > > > >                         
> > > > > > gl11.glBufferData(GL11.GL_ELEMENT_ARRAY_BUFFER,
> > > > > > modelData.indices.length * 2,
> > > > > > BufferUtil.createDirectShortBuffer(modelData.indices),
> > > > > > GL11.GL_STATIC_DRAW);
> > > > > >                         if (hasLightMap) {
> > > > > >                                 
> > > > > > gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, lightmapVBOId);
> > > > > >                                 
> > > > > > gl11.glBufferData(GL11.GL_ARRAY_BUFFER,
> > > > > > lightMapModelData.tex.length * 4,
> > > > > > BufferUtil.createDirectIntBuffer(lightMapModelData.tex),
> > > > > > GL11.GL_STATIC_DRAW);
> > > > > >                         }
> > > > > >                         BaseRenderer.checkErrors(gl11);
> > > > > >                         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 0);
> > > > > >                         
> > > > > > gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, 0);
>
> > > > > > -- Draw --
>
> > > > > >                         // use VBOs
> > > > > >                         gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, 
> > > > > > vertexVBOId);
> > > > > >                         gl11.glVertexPointer(3, GL10.GL_FIXED, 0, 
> > > > > > 0);
> > > > > >                         if (modelData.normals != null) {
> > > > > >                                 
> > > > > > gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, normalVBOId);
> > > > > >                                 gl11.glNormalPointer(GL10.GL_FIXED, 
> > > > > > 0, 0);
> > > > > >                         }
> > > > > >                                 
> > > > > > gl11.glBindBuffer(GL11.GL_ARRAY_BUFFER, texVBOId);
> > > > > >                                 gl11.glTexCoordPointer(2, 
> > > > > > GL10.GL_FIXED, 0, 0);
> > > > > >                         
> > > > > > //gl11.glBindBuffer(GL11.GL_ELEMENT_ARRAY_BUFFER, indexVBOId);
> > > > > >                         // the main draw call
> > > > > >                         gl11.glDrawArrays(GL11.GL_TRIANGLES, 0, 
> > > > > > vertexCount);
> > > > > >                         //gl11.glDrawElements(GL10.GL_TRIANGLES, 
> > > > > > vertexCount,
> > > > > > GL10.GL_UNSIGNED_SHORT, 0);
>
> ...
>
> read more »

-- 
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en

Reply via email to