Design of NondirectBufferWrapper causes memory corruption ?

Started by obelix, January 17, 2010, 23:07:29

Previous topic - Next topic

obelix

Hello Everyone,

I'm quite new to lwjgl so in case I'm doing something obviously wrong please don't hesitate to correct me.

The situation I ran into is as follows. I know that lwjgl can really only work with direct buffers. I also assumed the api will transparently handle ( through NondirectBufferWrapper ) the passing-in of a non-direct buffer, so I ended up coding the following:

        IntBuffer length = IntBuffer.allocate(1);        
        GL20.glGetProgram(program, GL20.GL_INFO_LOG_LENGTH, length);
        
        ByteBuffer logBuffer = ByteBuffer.allocate(length.get(0));        
        GL20.glGetProgramInfoLog(program, length, logBuffer);


Strangely, the first 4 bytes of logBuffer were ending up clobbered with what turned out to be the byte contents of length. It appears that NondirectBufferWrapper is keeping, per-thread, a single direct buffer so with a call that takes multiple buffers ( like glGetProgramInfoLog ) they will all get mapped to the same memory and things will end up being overwritten.

Am I missing something really huge here or is this an lwjgl bug ?

spasi

You're correct, this is an LWJGL bug. Multiple non-direct buffers in the same GL call will get mapped to the same direct buffer. You can workaround this limitation by using only one non-direct buffer per call.

Tbh, I'm not sure why would we need this kind of utility in LWJGL and I don't like the hidden performance cost. I'd rather have all LWJGL calls require direct buffers and have them throw an exception when a non-direct buffer is used. Is there any LWJGL user that benefits from this functionality?

Kai

In my optinion, don't let LWJGL do something that the user can/should do as well.

Most times, the user has a better understanding of its needs and requirements than a library (such as LWJGL) can guess, so the user should be aware of the need to give a direct buffer to LWJGL and in such cases, she can cache these buffers in her application more efficiently (because of the fact that she knows the application and its requirements) and can squeeze the most performance out of it.

spasi

That's my opinion as well, but I'm going to assume that this was put in LWJGL for a reason. I'll wait for Elias (that coded it) or any user (that's using it) to provide some input on the matter before making any changes.

edit: found some info here and here.

obelix

I personally vote for removing support for non-direct buffers completely. In its current form it's only luring the user into a false sense of security and encourages coding that incurs random performance penalties. The issue of buffer management is real and the user is probably better off being confronted with it from the start. I personally just changed the getCachedBuffers method to throw unconditonaly and I don't feel I've lost anything at all. OTOH, coding proper autowrapping seems time consuming and hence not worth it.

As far as usability perks go, call wrappers that take java strings and internally convert them to char* will be quite helpful. Similar for the opengl calls that return void but take an int* only to return a single length in it. However, as long as I need to put my string in a ByteBuffer to pass it in whether I also need to provide a direct buffer myself or not seems a very minor detail.

Matthias

I also vote to remove non direct buffer support.

But would be nice if some key methods like glGenBuffers, glGenTextures etc would have a version allocating extract 1 object and returning the handle as int rather then IntBuffer.

delt0r

I think getting rid of indirect bufferes it is not just a good idea but a needed api change. The extra cost of a buffer copy and then potential threads issues if you cache a direct buffer should not be hidden from the api user. The api user needs to know there buffers and when to allocate etc.

So i vote yes. get rid of indirect buffer support.
If you want a plot read a book and leave Hollywood out of it.

princec


Light232

Quote from: spasi on January 18, 2010, 12:02:15
You're correct, this is an LWJGL bug. Multiple non-direct buffers in the same GL call will get mapped to the same direct buffer. You can workaround this limitation by using only one non-direct buffer per call.

Tbh, I'm not sure why would we need this kind of utility in LWJGL and I don't like the hidden performance cost. I'd rather have all LWJGL calls require direct buffers and have them throw an exception when a non-direct buffer is used. Is there any LWJGL user that benefits from this functionality?
When performing read/write operations on the buffer its generally alot faster to use the heap*buffer as opposed to the direct*buffer
Copying from a gc managed array to a direct array became alot faster with the introduction of JNI1.6ish?(you have to use the proper functions..which im guessing LWJGL does not)