I noticed that Buffers.newDirectIntBuffer(int[]) does not set the limit of the buffer. This causes a driver crash on OSX.
When using this form: final IntBuffer indexBuf = Buffers.newDirectIntBuffer(triIndexes);This is the trace output when I upload the data to the driver: glBindBuffer(<int> 0x8893, <int> 0x3) glBufferData(<int> 0x8893, <long> 0, <java.nio.Buffer> java.nio.DirectIntBufferU[pos=0 lim=0 cap=89034], <int> 0x88E4) and finally the driver crashes when it is time to render: glDrawElements(<int> 0x4, <int> 0x15BCA, <int> 0x1405, <long> 0)# # A fatal error has been detected by the Java Runtime Environment: # # SIGSEGV (0xb) at pc=0x000000010fd4b3b0, pid=1443, tid=31031 # # JRE version: Java(TM) SE Runtime Environment (8.0-b132) (build 1.8.0-b132) # Java VM: Java HotSpot(TM) 64-Bit Server VM (25.0-b70 mixed mode bsd-amd64 compressed oops) # Problematic frame: # C [libsystem_platform.dylib+0x13b0] _platform_memmove$VARIANT$Nehalem+0x70 But if I do this: final IntBuffer indexBuf = Buffers.newDirectIntBuffer(triIndexes.length); for (int triIndex : triIndexes) { indexBuf.put(triIndex) ; } The trace for uploading the buffer is this: glBindBuffer(<int> 0x8893, <int> 0x3) glBufferData(<int> 0x8893, <long> 356136, <java.nio.Buffer> java.nio.DirectIntBufferU[pos=0 lim=89034 cap=89034], <int> 0x88E4) Notice the limit is set to the number of ints I put into the buffer and now the driver does not crash. Should I write a bug report or is this expected (i.e. limit not set) when using the array version of newDirectIntBuffer? |
Thank you, i think it is wise to file a bug-report.
I took a quick look and wrote a proposed "fix". By replacing the use of NIO Buffer rewind with clear. gluegen-rewind-to-clear.patch Please test! http://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html#clear%28%29 "clear public final Buffer clear() Clears this buffer. The position is set to zero, the limit is set to the capacity, and the mark is discarded. Invoke this method before using a sequence of channel-read or put operations to fill this buffer. For example: buf.clear(); // Prepare buffer for reading in.read(buf); // Read data This method does not actually erase the data in the buffer, but it is named as if it did because it will most often be used in situations in which that might as well be the case." |
OMG I'm sorry I left out a piece of code that I use. The 'working' case is this:
final IntBuffer indexBuf = Buffers.newDirectIntBuffer(triIndexes.length); for (int triIndex : triIndexes) { indexBuf.put(triIndex) ; } indexBuf.flip(); The flip() part is the essential thing and I think more appropriate than clear() in the Buffers class. Sorry I do not have a build setup for gluegen where I can test the patch :-/ |
Bug reported as https://jogamp.org/bugzilla/show_bug.cgi?id=1180
|
In reply to this post by jmaasing
It would be good to understand the root cause why the crash can happen when lim do not match capacity. The only reason i can think of that generates a crash is that the JVM garbage collector has decide to reclaim the memory that have been passed to the GPU. |
Actually I think it is my code. I used the buffer limit to calculate the amount of data when uploading data to the driver. Since limit was 0 who knows what crap the driver found when it tried to render the data :-) |
Administrator
|
On 07/24/2015 08:35 PM, jmaasing [via jogamp] wrote:
> Xerxes Rånby wrote > It would be good to understand the root cause why the crash can happen > when lim do not match capacity. > The only reason i can think of that generates a crash is that the JVM > garbage collector has decide to reclaim the memory that have been passed > to the GPU. > > Actually I think it is my code. I used the buffer limit to calculate the > amount of data when uploading data to the driver. Since limit was 0 who knows > what crap the driver found when it tried to render the data :-) <https://jogamp.org/bugzilla/show_bug.cgi?id=1180> Question remains, how did it (0 limit) happen? Please answer in related bug report and close it if proven to be your issue. I guess we are a bit 'crazy' about this issue, since iff this would be an internal bug within GlueGen and/or JOGL it is quite substantial (and would break everything). Hence .. we are a bit concerned and tedious now :) ~Sven signature.asc (828 bytes) Download Attachment |
I had some time to investigate this, the problem is in my expectations on what the Buffers class does. You are absolutely right in that limit is correctly set by the Buffers class. The difference is actually in the position. This test illustrates what my code did: public class BuffersTest { @Test public void testFlipReadOnExplicitlyPutBuffer() { IntBuffer explicit = Buffers.newDirectIntBuffer(3); explicit.put(1) ; explicit.put(2) ; explicit.put(3) ; explicit.flip() ; assertTrue(explicit.get() == 1) ; assertTrue(explicit.get() == 2) ; assertTrue(explicit.get() == 3) ; } @Test public void testFlipReadOnArrayCreatedBuffer() { IntBuffer implicit = Buffers.newDirectIntBuffer(new int[] {1,2,3}); implicit.flip() ; assertTrue(implicit.get() == 1) ; assertTrue(implicit.get() == 2) ; assertTrue(implicit.get() == 3) ; } } Notice that I 'flip()' the buffer before I read from them and this is the key problem. In the 'implicit' case the position on the returned buffer is set to '0'. I assumed it would be set to 3 so it would be the same as in the explicit but I assumed wrong. I do not consider this a bug, more a mistaken assumption on my part. I will close the bugzilla issue. Sorry for all the noise. |
Free forum by Nabble | Edit this page |