[Solved] ? Crash using VBO w/ GlDrawArrays and pBuffers ?

I get the following error using VBOs and GlDrawArrays() and with pBuffers…not sure if all of those are the cause or if only the first two.

The VM basically crashes with the above error…ie a hard crash with no log in Windows, in Linux 32 bit I got a log that pointed me to GlDrawArrays() as the crash stop point.

I’ve attached a compressed zip file to this post which I hope someone can test out for me…it contains a test project showing the issue.

The file is a NetBeans project but I changed the extension to .jar so I could upload it to this forum.

Take the file VboGlDrawArraysCrash.jar and RENAME it to VboGlDrawArraysCrash.zip and then extract the data to your desktop.

You need to update the jogl library paths within the project it get it to work. This code uses a modified version of the JOGLUTILS library to load 3DS files…the modifications are my VBO additions that I’ve not yet submitted for JOGLUTILS updates. I believe the VBOs are correct, and you can see what I do with setting them up in the model3ds/Model3DS.java file.

Here is a description of the code that you will see…I have a VboGlDrawArraysCrash.java code that basically sets up the panel containing a render panel on the left (areas/renderer/RenderPanel.java) and a JPanel with two pulldowns on the right side. In the left RenderPanel I display a BufferedImage obtained from a pBuffer that is generated in the renderer.

The renderer draws either a 3DS model or a Cube based on what you select in the “Area” pulldown: 3D Vehicle or Flat Plate. There are corresponding classes that render these two things: areas/vehicle/VehicleArea.java and areas/vehicle/FlatPlateArea.java. Each of these classes has a drawGL() method that does the drawing.

Ok, here are the instructions that will get you to CRASH your VM.

  1. Start the viewer
  2. select “Flat Plate” from the Area pulldown - it is defaulted to 3D Vehicle
  3. Change Resolution to anything you want.
  4. select “3D Vehicle” from the Area pulldown - ie. go back to where you started.

The above crashes the VM…initially I thought the cause was the of changing the resolution of the pBuffer (which is what the Resolution pulldown does) and it may be related but I don’t see why. In my case I recreate the pBuffer to fit the new resolution selection because the setSize() of the pBuffer is not yet implemented.

Clearly if you are viewing a 3DS vehicle (in this case a tie fighter) then the VBOs and GlDrawArrays() are working because you see them.

I can change to the Flat Plate view and back to 3D vehicle view multiple times and all things are rendered correctly. I can even change the resolution while I’m in the 3D Vehicle view and it works correctly. I can also switch to the flat plate view and change resolution and it also works…but now if in the flat plate view I switch resolutions and then change back to the 3D view then I get the VM crash…it just makes no sense what the cause is.

Even though I have multiple classes for rendering, I basically have the following simple code for the renderer:


 void display() {
    if (3D selected) {
       DrawModel3DS();
    } else if (Flat Plate Selected) {
       DrawFlatPlate();
    }
  }

So it is not like creating any new GLJPanel or new VBOs…I’ve created all of those things once and I simply switch which I display. It seems to work except for the once case above where I switch resolutions while in Flat Plate mode and then change the view to the 3D vehicle mode. If I’m in the 3D vehicle mode and change resolutions and then go to flat plate mode then it is still fine.

I’ve lost my mind…this is crazy. BTW, I know VBOs are the issue here because I can change my rendering from VBOs to Immediate mode rendering and everything works fine…only if I use the VBOs in the 3D model do I get the crash and it seems to occur in my render method at the glDrawArrays() calls.

Any thoughts???

Remember to rename the .jar attachment to .zip and unzip it to test out the code.

I haven’t checked out your code yet, but have you made sure that:
-nio buffers were re-winded before sending it to the vbos
-you’re using the correct buffer id’s
-tried using the ARB versions of all vbo related functions
-looked at the result from isFunctionAvailable() or isExtensionAvailable() from the GL
-made sure that your contexts aren’t being destroyed and re-initialized because of the GLJPanel

These are just some brainstorming ideas, but I hope that helps.

  1. I think that the nio buffers being rewinded I have done correctly. I do rewind my various buffers after I populate them, so I think this is ok.

  2. I am using the correct buffer ids. As a matter of fact the VBO works perfectly fine in all other cases. It’s not that the VBO fails but rather in these particular circumstances it fails but in such a weird way that I have no idea why.

I mean, I use the VBO and it works, I then introduce a pBuffer and it works. I can recreate the pBuffer based on a new resolution size and it works fine. For one display loop I turn of displaying the VBO (ie I simply don’t call it), I then change the pBuffer resolution by recreating the pBuffer, I then enable displaying of the VBO again and I get a crash. It’s not like I make any opengl/jogl call to disable the VBO prior to recreating the pBuffer, I simply have a boolean flag (essentially) which effectively displays a 3D cube instead of the VBO and then I reset the boolean flag and the VBO is displayed again and a crash occurs.

It just makes no sense…I mean, I can draw the VBO just fine, change the resolution by recreating the pBuffer and then the VBO is still fine, but somehow not drawing it for one display() loop causes it to fail in the next loop but only if the pBuffer is recreated.

Does that make sense??? It is beyond weird and that is why I tried to recreate my problem with as little code as possible in the example I created.

  1. I have not tried the ARB versions.

  2. I do use both isFunctionAvailable() and isExtensionAvailable() and they work and the VBOs work fine.

  3. I don’t believe any contexts are being destroyed because I don’t remove windows, I don’t resize them, I simply have a flag that determines what is drawn (specifically which ‘area’ is drawn) in the display() loop of the renderer.

thanks.

btw, I’m not the only one having this issue in the world, but there is so little info on this error or the cause that it is hard to figure out the solution.

Just to make sure, your vbos are re-made when you re-create the pbuffer, right? Or do you use context sharing?

No, they are not remade, because the init() is not being called…or at least it doesn’t seem to be called. The code is there that if init() is called then I will recreate the VBOs…until that point they seem be fine. I don’t do any context sharing because I don’t know how.

Basically in my init() method I have a call to the ‘areas.initGL(gl)’ method. In this initGL() method for the 3D vehicle I reload the VBO, reload the textures. But this is not being called, when I recreate the pBuffer. It is supposed to be?

I would question this if not for the fact that I can see 3D vehicle that uses VBOs update correctly when I recreate the pBuffers on changing resolutions. It only has an issue when I change to drawing the Flat Plate area (which is a 3D cube, or even drawing nothing), but while drawing nothing I then update the resolution and then switch to drawing the 3D Vehicle with VBOs and I get a failure. I’ve been trying to trace my pulldown menu calls to see if I set something or some flag but I just don’t see anything - it is a freaking mystery to me right now.

I’m not explaining this well because it is kind of hard to grasp what is happening here.

thanks.

I decided to put a simple call to init() from my display() just to force the init() call and force the VBO recreation and I think that seems to have done the trick. I mean, I don’t get a the crash anymore.

Besides context-sharing, what other way could I do this init() call??? From a pBuffer you can just do pBuffer.display() and that invokes the display loop, or should I just be creative and call it from within display() as an update is necessary?

Also, do you have any thoughts as to why I would get perfectly fine results when switching resolutions (ie recreating the pBuffer) but only when I switched to displaying something else for a display() cycle it caused the VM to crash?

I took a quick look at your source code and one thing struck as the likely source of your problem. In the init() method of your AreaRenderer class, you have:


      AbstractArea area = areas.get(selectedArea);
      if (area != null) {
        area.initGL(gl);
      }

but the init() method is only called once per lifecycle of a GLContext. I can see a problem happening if the you need to display one area, but it’s not the currently selected one. Then in it’s init() method, the initGL() wouldn’t actually be called, so the rendering would be trying to use vbos/etc. that weren’t actually set up.

Now I don’t know if you’ve somehow guaranteed that an area is always ‘selected’ before it’s rendered, but I think a better approach would be to have an AreaRenderer instance associated with each AbstractArea, and the AreaRenderer holds onto its associated AbstractArea. This might look like:


class AreaRenderer implements GLEventListener {
  private AbstractArea area;

  public AreaRenderer(AbstractArea area) {
      this.area = area;
      ... blah ....
  }
 
  .... more methods ...

  public void init(GLAutoDrawable gl) {
     .. as before

     area.initGL(gl)
  }
}

Then also, in your RendererPanel, you’d need to store an AreaRenderer per AbstractArea, possibly using a HashMap<AbstractArea, AreaRenderer> or a HashMap<String, AreaRenderer> (where the string key is the same used to look-up the AbstractArea in your existing map).

Thanks for looking at my code in so much detail. I agree with you that the init() is a problem because I was able to fix the issue by forcing an init() from the display() loop and that forced the recreation of the VBOs.

I think you may have hit on the exact issue here now that I think about it more clearly. Basically what happens is that the recreation of the pBuffer() probably destroys the context and actually calls init() to recreate it. Well, when I was in the Flat Plate view, I changed the resolution so it created a new pBuffer and called init() on the Flat Plate area - which was the one currently selected. The minute I then changed to the 3D Vehicle area, where VBOs are but were not reloaded because init() was not called on them specifically, then it crashed.

Dude, you ROCK!!!

This is exactly the issue…I basically didn’t realize that context was destroyed and init() was actually being called because I wasn’t seeing some of my System.out.println comments so I assumed incorrectly. In fact init() was being called but because the 3D Vehicle area didn’t gets its VBOs recreated then they failed.

Your suggestion of having a render with each Area makes sense but I wanted to minimize the use of renderers and instances as much as possible, so I wanted to share this renderer but I just didn’t think about this issue in advance. I’ll be able to solve it now…I will simply do some tracking of whether I need to call init() or not based on my situation.

Thanks again for your time and your help.