PDA

View Full Version : VBO Indexarray crashes on nVidia



Jan
05-02-2007, 08:08 AM
Hi

I am hunting down bugs in my app, and now it seems to be related with index arrays in video memory, so i open up a new thread for this.

I have two VBOs. One for data, one for indices. If i bind both and issue a drawcall, it runs flawlessly on ATI, but crashes immediately on nVidia.

If i don't put the index array into a VBO, it also runs as expected on nVidia.

Here is my Code:



Setup:
------

glGenBuffers (1, &m_uiVertexBufferID);
glBindBuffer (GL_ARRAY_BUFFER_ARB, m_uiVertexBufferID);
glBufferData (GL_ARRAY_BUFFER_ARB, m_uiElementSize * uiVertexCount, (void*) &m_pInterleavedData[0], GL_STATIC_DRAW);

glGenBuffers (1, &m_uiIndexBufferID);
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, m_uiIndexBufferID);
glBufferData (GL_ELEMENT_ARRAY_BUFFER, iIndices * sizeof (int), (void*) &m_pIndices[0], GL_STATIC_DRAW);


Bindbuffer:
-----------

glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, m_uiIndexBufferID);
glBindBuffer (GL_ARRAY_BUFFER_ARB, m_uiVertexBufferID);

for (int i=1; i < max; ++i)
{
glEnableVertexAttribArray (i);
glVertexAttribPointer (i, ...);
}

// array 0 is set LAST, as nVidia advises in their paper about VBOs
glEnableVertexAttribArray (0);
glVertexAttribPointer (0, ...);



Render:
-------

Bindbuffer ();

// this crashes
glDrawElements (GL_TRIANGLES, uiCount, GL_UNSIGNED_INT, BUFFER_OFFSET (uiFirstVertex * sizeof (int)));

// this works just fine
glBindBuffer (GL_ELEMENT_ARRAY_BUFFER, 0);
glDrawElements (GL_TRIANGLES, uiCount, GL_UNSIGNED_INT, &amp;m_pIndices[uiFirstVertex]);It seems, as if the driver doesn't like indices to lay in video memory.

This is on a Geforce 7600 GT, Forceware 93.71.

On an ATI Radeon X1600 Mobility it runs just fine. Tried several different setups, changing the order of execution, etc. didn't change anything. The moment i put the Indexdata into a VBO it crashes on nVidia.

Thanks,
Jan.

martinsm
05-02-2007, 08:29 AM
Does this is true: uiFirstVertex + uiCount <= iIndices ?

Are VertexAttribPointer's correctly specified?

Have you tried same code using Vertex Arrays - skip bindbuffer/bfferdata stuff, just use real memory pointers, instead of NULL. Is then your code working?

mfort
05-02-2007, 08:51 AM
Try drivers 84.21
http://www.nvidia.com/object/winxp_2k_84.21.html

knackered
05-02-2007, 09:30 AM
One thing, if you don't use glDrawRangeElements, the driver may have to copy your indices back to system memory to examine them.
I'm not sure if this is entirely true, but it's the assumption I've always made...hence I never use glDrawElements.

martinsm
05-02-2007, 10:11 AM
Why would driver want to examine them?

Jan
05-02-2007, 10:20 AM
@martinsm: I check for uiFirstVertex + uiCount <= iIndices, and it is true.

VertexAttribPointers should be correct, right now i only use position, and it works, if indices are not in a VBO, so it should be ok.

I did try it without VBOs, with simple vertex arrays, though i didn't test that on nVidia, only on ATI. Maybe i'll try it later again.

@mfort: Why should i use this driver? Is there any significant difference?

@knackered: I know, i just use glDrawElements right now to rule out the possibility, that i might specify wrong lower and upper bounds.

Jan.

martinsm
05-02-2007, 12:10 PM
Originally posted by Jan:
I did try it without VBOs, with simple vertex arrays, though i didn't test that on nVidia, only on ATI. Maybe i'll try it later again.And did it work?

mfort
05-02-2007, 12:43 PM
@Jan: Yes, I had to downgrade NV drivers to 8x due to PBO related crashes in 9x drivers. 8x was OK. Probably they changed something. I believe VBO are implemented the same way as PBO.

Lord crc
05-02-2007, 02:48 PM
I had this issue a couple of times (although I didnt try ATI). Both times I had messed up the glVertexPointer stuff (saying I had 3 components per element when I actually uploaded 4 causing a memory overrun, or similar). Worked fine without index VBO's, crashed right away with.

knackered
05-03-2007, 02:30 AM
Originally posted by martinsm:
Why would driver want to examine them? I think it needs to know which vertices the indices reference, and this information becomes part of the command stream to the GPU for it to DMA the correct block of vertices if necessary.

Jackis
05-03-2007, 03:27 AM
Sometimes I saw similar thing, floating point exception in nvoglnt.dll on a draw call (independent of glDrawElements or glDrawRangedElements). Unfortunately, this was really hard to reproduce, this crash is not stable. But all the indices and vertices were fine.

Masking floating point exceptions, surely, helps, and everything draws as usual, but sometimes, when unmasking them, exception occures.

But, as I understand, it is not your case.

Komat
05-03-2007, 10:58 AM
Originally posted by knackered:

Originally posted by martinsm:
Why would driver want to examine them? I think it needs to know which vertices the indices referenceAnalyzing the indices on the cpu during call that is not recorded into display list would be counterproductive. When using the glDrawElements the driver can always assume that all vertices inside the buffer are referenced by the indices when it needs that information somewhere.

Komat
05-03-2007, 11:02 AM
In the past I had some VBO related crashes. I am not sure if I remember that correctly however the crash happened when several VBOs containing different amount of vertices (based on stride and buffer size) were bound simultaneously during draw call.

Relic
05-04-2007, 12:01 AM
This happens on the first run through that code?


for (int i=1; i < max; ++i)
{
glEnableVertexAttribArray (i);
glVertexAttribPointer (i, ...);
}
glEnableVertexAttribArray(0);
glVertexAttribPointer (0, ...);If max changes, do you also have the matching code disabling the arrays not used anymore or are there arrays left enabled you don't use in following runs.

BTW, if you want to set attrib 0 last, just invert the loop counter => two lines of code eliminated.
The indices should really be unsigned int.

For a piece of paranoia, I've seen weird things happening with macros:

BUFFER_OFFSET (uiFirstVertex * sizeof (int)));Do not put a white space between the macro and the bracket if the macro is defined as BUFFER_OFFSET(_X)

knackered
05-04-2007, 02:15 AM
Originally posted by Komat:
Analyzing the indices on the cpu during call that is not recorded into display list would be counterproductive. When using the glDrawElements the driver can always assume that all vertices inside the buffer are referenced by the indices when it needs that information somewhere. Well that gem was touted on these forums some time ago, when people were discouraged from putting indices into VBO (or VAR maybe). The reasoning was that the cpu did indeed walk the indices to gather the range information.

Jan
05-04-2007, 06:10 AM
I wasn't able to try it with downgraded drivers, yet, though i don't think trying it would make sense, since it is most certainly not a driver issue (else Doom 3 etc. wouldn't run on that hardware) and also it just needs to run on all drivers, since it is for university and i have no control over the drivers installed there. So even if it was a driver issue, i would need to work around it.

It doesn't seem to be related to floating-point exceptions.

@Komat: I heard one can bind several VBOs simultaniously, however i don't know how that can actually be achieved. I don't use it, all my data is in one VBO (and indices in a second one).

@Relic: This happens every time i bind the VBO. Afaik i need to set up all the arrays everytime i bind a new VBO, since glBindBuffer resets all vertex array state. Or does it set the vertex array state to how it was, when the same VBO was bound last? In my opinion the spec quite clearly states the opposite.
I know i could invert the loop, that was just a quick and dirty way to make sure array 0 was bound last.
About the paranoia: I changed it to what you said, however there seems to be no difference.

So far i haven't been able to get it to work on nVidia. I think for now i will work around it, by leaving the Indices in system memory and in a few days i will write a small test application to try to make it work on nVidia. I have looked and rearranged the code a hundred times now and cannot find anything, that might make it break. But then we have all been there before. I don't believe it's a driver bug.

Thanks for your suggestions,
Jan.

knackered
05-04-2007, 07:22 AM
binding several buffers:-

for (int i=1; i < max; ++i)
{
glBindBuffer (GL_ARRAY_BUFFER_ARB, m_uiVertexBufferID[i]);
glEnableVertexAttribArray (i);
glVertexAttribPointer (i, ...);
}The bind command simply states that any gl**Pointer functions from now on refer to offsets within this buffer.

Korval
05-04-2007, 10:49 AM
Well that gem was touted on these forums some time ago, when people were discouraged from putting indices into VBO (or VAR maybe). The reasoning was that the cpu did indeed walk the indices to gather the range information.First, it was only ever nVidia who suggested this. ATi was decidedly neutral on the subject.

Second, I would hope by now that nVidia has dealt with whatever hardware issue provoked this rather silly usage pattern.

knackered
05-04-2007, 12:01 PM
thanks for clearing that up, korval.
much appreciated.

Jan
05-08-2007, 04:16 AM
Ok, did some thorough tests, here are the results:

On ATI everything works just fine.

On nVidia, using VBOs for vertex-data always works fine. Putting index-data into a VBO works fine for a limited amount of data. Speed is ok, it's stable and all.

However, in my real-world app, i have 2 mio vertices, and around 700K triangles. Putting that much data AND the corresponding indices into VBOs crashes on nVidia.

That is, for now i put the vertex-data into ONE VBO and the index-data into ONE VBO. I don't split the data into smaller chunks.

So i made a test-app. My test-app uses quads. One quad = 4 vertices = 2 triangles = 6 indices (unsigned int).

With 260K quads it runs "fast" and stable on a Geforce 7600, with latest official drivers (from November). I render it using one drawcall.

With more than 260K quads it crashes, when the indices are in a VBO. It works fine, even with 1M quads, when the indices are in RAM.

So i switched from rendering triangles to rendering quads, decreasing the number of indices needed per quad. The limit stays at 260K quads. So that seems not to matter.

My vertex-data consists of position and color information. Now i increased the VBO size by putting fake texcoords and normals into the array. I don't fetch that data from within the shader (which just passes the color through), but it more than doubles the per-vertex data. The limit stayed at 260K quads, it did not decrease. So i assume it is not an issue regarding memory consumption.


So what i tried was:
1. varying number of vertices
2. varying number of indices
3. varying size of per-vertex data
4. disabling on GPU indices

2 and 3 seem to have no effect. 4 fixes the problem completely. 1 is the problem: if you have few enough vertices, it works, if you reach some limit, it crashes.

I uploaded my test app here. (http://www.artifactgames.de/Sonstiges/nvtest.zip)

So, you can try it yourself. I included the source-file containing the buffer-setup and the rendering code. It is a bit complicated, because of the several options and the quick-and-dirty implementation, but i am pretty sure it is error-free. If you see an error, please tell me. Would be cool, if you could give me some feedback, whether it runs on your hardware.

If you don't see anything after loading, you need to look around, using the mouse, until you see the hippy-quads.

Any other hints / advice is very welcome.
Jan.

yooyo
05-08-2007, 06:53 AM
wow.. this app just kill Windows. Render few frames, and screen goes black. All I can do is hard reset.

Jan
05-08-2007, 09:29 AM
Sorry about that!

yooyo
05-08-2007, 05:12 PM
NP :)
This app crash my P4 Dual core + 7600GT (PCIE) + 155.19 drivers, but it works on my laptop (with GF5600-Go and 96.89 drivers)

Korval
05-08-2007, 05:39 PM
2 mio verticesMio?


The limit stayed at 260K quads, it did not decrease. So i assume it is not an issue regarding memory consumption.Sounds like some internal counter is being overloaded. Possibly around 2^18th bits in size?

I'm curious: what happens if you make it two draw calls?


This app crash my P4 Dual core + 7600GT (PCIE) + 155.19 drivers, but it works on my laptop (with GF5600-Go and 96.89 drivers)I wasn't aware that nVidia's driver versions had gotten up into the 150's.

Komat
05-08-2007, 06:02 PM
Originally posted by Korval:
I wasn't aware that nVidia's driver versions had gotten up into the 150's. The latest beta compatible with GF7 and XP is 160.03 Bad thing is that the old classic control panel is gone and only the new monstrosity remains, at least it was reworked for the latest version so it is more intuitive.

Komat
05-08-2007, 06:15 PM
On my system (Dualcore Athlon 64 X2, Win XP, GF7800GTX) with 91.something drivers the tested application worked (at least some long box was visible if that is what it should display) with Test_100K and caused blue screen with the Test_300K.

After upgrade to 160.03 the application shows nothing and the message box about start of rendering that was displayed with old drivers is not shown. Other OGL applications I tested still work.

Jan
05-09-2007, 01:43 AM
mio = million
Is that abbreviation not used in the english language?

I haven't tested using more drawcalls explicitly in this app, but my real application, that had the same problem, used a few hundred drawcalls and only rendered a few hundred to thousand triangles per call. I will test it with more drawcalls soon, but i haven't done it yet.

Komat: yes you see a "long box". It's actually thousands of quads one after another.

Interesting, that it doesn't show anything with with newer drivers, not even the MessageBox.

Hm, so you suggest, that it is possible nVidia has internal counters, that have lower range? If that's indeed the problem, i can work around that. An official statement from nVidia, whether this is true, would be cool. I am just a bit confused, because it works with indices in system memory.

Thanks for being so brave to test it.
Jan.

Komat
05-09-2007, 03:42 AM
In DX capability viewer the Nvidia drivers on GF7800 report that they support maximal vertex index of 1048575 (0xFFFFF in hexa) so if you use bigger index in the OGL, the driver must do some magic with that and from results it seems that it fails to do that correctly.

Jan
05-09-2007, 07:41 AM
Well, 260K quads = 4*260K vertices = 1040000 vertices. A bit more and it crashes.
That absolutely matches my observations.

I still don't get it, why it should work with indices in system memory, but well, what would a world without mysteries be?

Thank you Komat!
Jan.

knackered
05-09-2007, 09:07 AM
still, never mind eh?

barthold
05-09-2007, 10:23 AM
Jan,

we'll take a look. Thanks for the test app, that helps a lot getting to the bottom of this!

Barthold
NVIDIA

Vexator
05-09-2007, 11:13 AM
ah general question - is it a good idea to store indices in graphics card memory? i'm quite sure someone from the forums advised me not to do it.

AlexN
05-09-2007, 11:54 AM
Yes, it is a good idea to store indices in graphics card memory. If the graphics card does not directly support this (geforce 3/4?) then the GL driver can stick them in system memory for you, so it shouldn't require any effort on your part.

Jan
05-09-2007, 12:24 PM
@Barthold: Great, thank you. If you need the full source for the test-app, i can trim it down a bit and reduce it to a stand-alone GLUT application. Just let me know, whether that would help you.

@knackered: I don't get it, what do you mean?

Jan.

knackered
05-09-2007, 12:30 PM
sorry, I was just bored, forget I said anything.

heppe
03-06-2008, 02:13 AM
Was there ever any resolution to this one? I seem to be bumping up against a similar issue -- crashes GeForce, but survives Radeon. Here are the known data points in my case:
GeForce 7300gs, Intel Express 965, Mesa3D linux: crash
Radeon x1600, Quadro, FireGL: works
I'm putting both vertices into a GL_ARRAY_BUFFER_ARB and
indices into a GL_ELEMENT_ARRAY_BUFFER

glExpert reports nothing useful.
gDebugger comes up clean.
the crash leaves no useful stack.

I'm concentrating on GeForce for the moment, since that's what is currently on my desktop. Driver is dated 12/5/2007. Driver version is reported as 6.14.11.6921 (is that right? I don't remember NV driver versions being formatted like that).

Jan
03-06-2008, 04:45 AM
Hi there

I don't have the whole thread in mind anymore, but i assume i mentioned, that i partition my vertex-arrays now into chunks each containing < 2^16 vertices. That solved the problem on all nVidia hardware, that i tested it on (Geforce 7 and 8, though 8 had never the problem in the first place).

Whether more recent drivers solved the issue, i don't know. I never got any additional feedback from nVidia.

Since using vertex-arrays with < 2^16 vertices gives much better performance anyway, i didn't mind about the bug anymore.

Jan.

-NiCo-
03-06-2008, 04:54 AM
GeForce 7300gs, Intel Express 965, Mesa3D linux: crash


You are not using the nvidia drivers, but the mesa3d (http://www.mesa3d.org/) software implementation. Make sure your graphics card drivers are installed correctly.

heppe
03-06-2008, 11:29 AM
Using mesa3d software was on purpose. We wanted an implementation we could debug into to try to decode what was going on.

It's possible that this is a different bug from the one that Jan originally posted. In my case it doesn't need to be big data.

heppe
03-06-2008, 11:25 PM
Now it's starting to look like multiple different bugs for the separate platforms. On each of the 3 crashing platforms, slightly different actions trigger the crashes. I believe I've identified what is causing the Mesa3D crash -- it's a buffer overrun (our fault). In the case of the Intel and GeForce crashes, though, I am triggering it with code that I know should not be causing buffer overruns.

Relic
03-07-2008, 02:59 AM
Driver version is reported as 6.14.11.6921 (is that right? I don't remember NV driver versions being formatted like that).


That's the Windows way to number drivers.
If you stare long enough at that version number you'll find that it's a 169.21 driver.