Bug 12502 - Corrupt text in World of Warcraft when VBOs are enabled.
Summary: Corrupt text in World of Warcraft when VBOs are enabled.
Status: RESOLVED FIXED
Alias: None
Product: Mesa
Classification: Unclassified
Component: Drivers/DRI/r200 (show other bugs)
Version: git
Hardware: x86 (IA32) Linux (All)
: medium normal
Assignee: Default DRI bug account
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-09-20 11:43 UTC by Chris Rankin
Modified: 2010-06-07 11:58 UTC (History)
0 users

See Also:
i915 platform:
i915 features:


Attachments
Warcraft with stretched-text corruption. (208.12 KB, image/jpeg)
2007-09-20 11:46 UTC, Chris Rankin
Details
Warcraft with missing-text corruption (170.68 KB, image/jpeg)
2007-09-20 11:47 UTC, Chris Rankin
Details

Description Chris Rankin 2007-09-20 11:43:30 UTC
When GL_ARB_vertex_buffer_object is enabled, all of the text messages in World of Warcraft disappear.

Originally, all of the text used to appear but be "stretched" to the bottom-lefthand corner of the screen. However, as of this commit:

d8c6719f95b1543296ac954f95d13b048ae48634 is first bad commit
commit d8c6719f95b1543296ac954f95d13b048ae48634
Author: Brian <brian.paul@tungstengraphics.com>
Date:   Mon Aug 20 13:12:20 2007 +0100

    refactor bounds checking code


the text disappeared instead.
Comment 1 Chris Rankin 2007-09-20 11:46:14 UTC
Created attachment 11661 [details]
Warcraft with stretched-text corruption.
Comment 2 Chris Rankin 2007-09-20 11:47:00 UTC
Created attachment 11662 [details]
Warcraft with missing-text corruption
Comment 3 Chris Rankin 2007-09-22 06:05:19 UTC
Warcraft seems to be tripping on this check in _mesa_validate_DrawRangeElements():

      /* make sure count doesn't go outside buffer bounds */
      if (indexBytes > ctx->Array.ElementArrayBufferObj->Size) {
         _mesa_warning(ctx, "glDrawElements index out of buffer bounds");
         return GL_FALSE;
      }

Interestingly, it looks as if ctx->Array.ElementArrayBufferObj->Size is always equal to "12" when this check fails. Why 12?
Comment 4 Brian Paul 2007-09-22 16:10:25 UTC
'Size' is the user-provided VBO size, set when the app calls glBufferData().

With gdb, please run:
  print *ctx->Array.ElementArrayBufferObj
  print indexBytes
  where
Comment 5 Chris Rankin 2007-09-22 17:18:02 UTC
(In reply to comment #4)
> 'Size' is the user-provided VBO size, set when the app calls glBufferData().
> 
> With gdb, please run:
>   print *ctx->Array.ElementArrayBufferObj
>   print indexBytes
>   where

I'm running WoW via wine; can I still use gdb? I'm currently putting a lot of fprintfs into main/bufferobj.c and am seeing the following:

_mesa_BufferDataARB: size=12
** target=GL_ELEMENT_ARRAY_BUFFER_ARB
** Calling BufferData(12)
_mesa_buffer_data: Size=12

MapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_BufferDataARB: size=144
** target=GL_ARRAY_BUFFER_ARB
** Calling BufferData(144)
_mesa_buffer_data: Size=144

MapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_BufferDataARB: size=12
** target=GL_ELEMENT_ARRAY_BUFFER_ARB
** Calling BufferData(12)
_mesa_buffer_data: Size=12

MapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_BufferDataARB: size=49152
** target=GL_ARRAY_BUFFER_ARB
** Calling BufferData(49152)
_mesa_buffer_data: Size=49152

MapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_BindBufferARB:
bind_buffer_object:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB
glDrawRangeElements index out of buffer bounds: 192 12

... etc. So it *looks* as if the most recent call to _mesa_BufferDataARB with target=GL_ELEMENT_ARRAY_BUFFER_ARB really was for 12 bytes. However, this doesn't explain how presumably the fglrx driver used to cope with the same program.

Having said all this, I've noticed that the text doesn't always disappear immediately, and during the time that it is working OK I see stretches of DEBUG statements like:

_mesa_BufferDataARB: size=576
** target=GL_ELEMENT_ARRAY_BUFFER_ARB
** Calling BufferData(576)
_mesa_buffer_data: Size=576

MapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

_mesa_BufferDataARB: size=49152
** target=GL_ARRAY_BUFFER_ARB
** Calling BufferData(49152)
_mesa_buffer_data: Size=49152

MapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_UnmapBufferARB:
** target=GL_ARRAY_BUFFER_ARB

_mesa_BindBufferARB:
bind_buffer_object:
** target=GL_ELEMENT_ARRAY_BUFFER_ARB

i.e. calls to populate ElementArrayBufferObj with 576 bytes.

BTW, the _mesa_warning message in _mesa_validate_DrawRangeElements() incorrectly mentions glDrawElements instead of glDrawRangeElements.
Comment 6 Chris Rankin 2007-09-23 05:27:28 UTC
(In reply to comment #4)
> 'Size' is the user-provided VBO size, set when the app calls glBufferData().
> 
> With gdb, please run:
>   print *ctx->Array.ElementArrayBufferObj
>   print indexBytes
>   where

I'm having trouble using gdb with Wine, so I've resorted to fprintf() instead. In this example, indexBytes = 192, although it looks like it can take other "random" even values up to 5064. The contents of ElementArrayBufferObj do not change.

glDrawRangeElements index out of buffer bounds: indexBytes=192 Size=12
ElementArrayBufferObj:
- RefCount: 2
- Name: 5
- Usage: 35040
- Access: 35002
- Pointer: (nil)
- Size: 12
- Data: 0x68ff29f0
- OnCard: 0


Comment 7 Brian Paul 2007-09-23 08:56:09 UTC
What are the parameters to glDrawRangeElements when you get the warning?

What happens if you disable the indexBytes check?

Why do you say ""In this example, indexBytes = 192, although it looks like it can take other "random" even values up to 5064.""?  Where does 5064 come from?  What's random about it?
Comment 8 Chris Rankin 2007-09-23 09:54:19 UTC
(In reply to comment #7)
> What are the parameters to glDrawRangeElements when you get the warning?

Here are a few examples:

glDrawRangeElements index out of buffer bounds: indexBytes=408 Size=12
ElementArrayBufferObj:
- RefCount: 2
- Name: 5
- Usage: 35040
- Access: 35002
- Pointer: (nil)
- Size: 12
- Data: 0x691840b0
- OnCard: 0
Mode=4, Start=0, End=135, Count=204, Type=5123

glDrawRangeElements index out of buffer bounds: indexBytes=3648 Size=12
ElementArrayBufferObj:
- RefCount: 2
- Name: 5
- Usage: 35040
- Access: 35002
- Pointer: (nil)
- Size: 12
- Data: 0x691840b0
- OnCard: 0
Mode=4, Start=0, End=1215, Count=1824, Type=5123

glDrawRangeElements index out of buffer bounds: indexBytes=192 Size=12
ElementArrayBufferObj:
- RefCount: 2
- Name: 5
- Usage: 35040
- Access: 35002
- Pointer: (nil)
- Size: 12
- Data: 0x691840b0
- OnCard: 0
Mode=4, Start=0, End=63, Count=96, Type=5123

> Why do you say ""In this example, indexBytes = 192, although it looks like it
> can take other "random" even values up to 5064.""?  Where does 5064 come from? 
> What's random about it?

This error message appears many times, with a variety of different values of indexBytes. 5064 is simply the largest example value.

> What happens if you disable the indexBytes check?

I'm sure that I had an "access violation" the last time I tried this. However, this time I just saw the return of the "stretched text" corruption instead.
Comment 9 Brian Paul 2007-09-23 12:53:12 UTC
I don't see any indications of a bug in Mesa so far.  The parameters and indexBytes look OK.

I guess one experiment to try would be to force disabling of GL_ARB_vertex_buffer.
You can do that by going into src/mesa/main/extensions.c and changing "GL_ARB_vertex_buffer" in some trivial way, like inserting "foo" in the middle.
If the app is checking the GL_EXTENSIONS string (like it should) it won't use VBOs.
Comment 10 Chris Rankin 2007-09-23 13:57:26 UTC
(In reply to comment #9)
> I don't see any indications of a bug in Mesa so far.  The parameters and
> indexBytes look OK.

The problem is the way that the writing disappears after an undetermined interval. It's not as if the writing *never* works with GL_ARB_vertex_buffer_object disabled. But once it does stop working, you need to restart the game to get it back.

> I guess one experiment to try would be to force disabling of
> GL_ARB_vertex_buffer.

Wine has a way of doing this (you mean GL_ARB_vertex_buffer_object?) already, and this is how I usually play WoW. However, I would rather help fix the problem than simply avoid it. Neither fglrx nor nvidia needs this workaround.

Can Mesa have only one ElementArrayBufferObj at any one time? Because WoW *seems* to be expecting the one with the text information to be loaded once at start up, and then it keeps trying to use it. However, Mesa seems to drop it after a while.
Comment 11 Chris Rankin 2007-09-23 16:01:58 UTC
(In reply to comment #10)
> It's not as if the writing *never* works with GL_ARB_vertex_buffer_object disabled.

Oops - I meant "enabled", not "disabled" there. Enabling GL_ARB_vertex_buffer_object makes all the text disappear after a short yet undetermined period.
Comment 12 Brian Paul 2007-09-24 08:17:13 UTC
OK, I wasn't clear on that.

My only guess at this point is that maybe the vertex element buffer is not getting unbound at some point so the glDrawRangeElements() is inadvertantly using a VBO.  Maybe try:

1. Insert a printf in _mesa_BindBufferARB(), printing the arguments.
2. When you print the parameters to glDrawRangeElements, also print the 'indices' pointer value.  If it looks like a real pointer address (and not a small integer) that's a good sign that we're using a VBO when we're not supposed to.
Comment 13 Chris Rankin 2007-09-24 13:02:19 UTC
(In reply to comment #12)
> 1. Insert a printf in _mesa_BindBufferARB(), printing the arguments.

_mesa_BindBufferARB(target=34962, buffer=14)
_mesa_BindBufferARB(target=34962, buffer=2)

and

_mesa_BindBufferARB(target=34963, buffer=1)
_mesa_BindBufferARB(target=34963, buffer=3)
_mesa_BindBufferARB(target=34963, buffer=4)
_mesa_BindBufferARB(target=34963, buffer=5)

> 2. When you print the parameters to glDrawRangeElements, also print the
> 'indices' pointer value.

When glDrawRangeElements() fails, indices is always NULL.
Comment 14 Adam Jackson 2009-08-24 12:28:05 UTC
Mass version move, cvs -> git
Comment 15 Chris Rankin 2010-06-07 11:58:07 UTC
Amazingly, this bug is now fixed with Mesa 7.9-git as well. VBOs are enabled, and the text remains readable.

And the minimap in the top-right corner of the screen isn't a large, blank white circle any more either: I actually now see a corrupted version of what is supposed to appear there.


Use of freedesktop.org services, including Bugzilla, is subject to our Code of Conduct. How we collect and use information is described in our Privacy Policy.