Imagination PowerVR SDK Blog

Crashing glDrawElements - a little experiment

pvrvframe
pvrtrace

#1

Good morning,

In my pursuit to find a mysterious crash inside the glDrawElements function using the Windows 32 bit version of the latest PowerVR GLES emulator libraries I’ve started doing some experiments with the examples, more precisely with the OGLES3ChameleonMan example from the 3.5 SDK. I changed the example a bit so that it tries to allocate the vbos in every frame, consequently crashing at some point. The slightly modified OGLES3ChameleonMan.cpp is in the attachment.

What makes me wonder however isn’t that it crashes, but how it crashes. All the code should do now is allocate more and more vbos using glGenBuffers with ever increasing handles and glBufferData. Consequently it crashes at some point, but after allocating merely 300 or so different glGenBuffers handles. The application also isn’t that large in memory (~ 60 mb once it crashes) so there shouldn’t be a bad alloc. I never get an opengl error via glgetError, not even GL_OUT_OF_MEMORY, I also checked using PVRTrace recorder.

Is this behavior normal or may it be the result of a bug?

Build environment is Visual Studio 2012 SP 1. Platform is Windows 7. AMD Catalyst version is 15.7.1.

Regards


#2

Hi Rodger,

Thanks for reporting the issue and sharing the modified code with us. We’ll try to reproduce the problem on our side and will get back to you.


#3

Hello Roger,

Could you please confirm the size of the glBufferData calls and if graphics card memory is being exhausted? GPU memory is not counted as process memory.

On a discrete graphics card you can use a utility such as GPU-Z - http://www.techpowerup.com/gpuz/. If you check the ‘Memory Used’ field in ‘Sensors’ it should indicate how much GPU memory is currently used.

Thanks,
Paul


#4

Ok, here’s the data.

The images are taken at the moment when the application crashes in glDrawElements and the debugger comes to a hold.

I suppose you need the Memory Usage (Dedicated) and the Memory Usage (Dynamic) parameters. I switched them to “Show Highest Reading” to demonstrate that there is still a lot of GPU memory available (the card has 1024 mb).

The glBufferData calls up to the crash should try to allocate memory of about 3-6 MB.

Regards

[attachment file=53332]

[attachment file=53333]


#5

Hello Roger,

I ran your modified example on my machine and the application continues running for a long time (Nvidia GT 730). GPU-Z shows the application consuming nearly all VRam (2GB) by the end. Then there is a fault in the driver dll.

This was using latest PVRVFrame from the 16.1 release.

We do have AMD based systems which I will request the PVRVFrame team to test on.

Thanks,
Paul.


#6

Hello,

it may very well be an ATI problem. Here a callstack of the crash:

atioglxx.dll!689a0966()	Unbekannt
[Unten angegebene Rahmen sind möglicherweise nicht korrekt und/oder fehlen, keine Symbole geladen für atioglxx.dll]	
atioglxx.dll!688e7844()	Unbekannt
atioglxx.dll!6895acab()	Unbekannt
atioglxx.dll!688f5329()	Unbekannt
atioglxx.dll!68b4de03()	Unbekannt
atioglxx.dll!6886f0ce()	Unbekannt
libGLESv2.dll!0fffd0a7()	Unbekannt
libGLESv2.dll!0ffe7e2f()	Unbekannt
libGLESv2.dll!0ffaedd1()	Unbekannt
libGLESv2.dll!0ff930ab()	Unbekannt
libGLESv2.dll!0ffb0d36()	Unbekannt
libGLESv2.dll!0fffd0a7()	Unbekannt
libGLESv2.dll!0ffb0c8e()	Unbekannt
libGLESv2.dll!0ffd355b()	Unbekannt
libGLESv2.dll!0ffd34dd()	Unbekannt
libGLESv2.dll!0ffb126f()	Unbekannt
libGLESv2.dll!0ffc835c()	Unbekannt

> OGLES3ChameleonMan.exe!OGLES3ChameleonMan::DrawSkinnedMesh(int i32NodeIndex) Zeile 867 C++
OGLES3ChameleonMan.exe!OGLES3ChameleonMan::RenderScene() Zeile 694 C++
OGLES3ChameleonMan.exe!PVRShellInit::Run() Zeile 1621 C++
OGLES3ChameleonMan.exe!WinMain(HINSTANCE__ * hInstance, HINSTANCE__ * hPrevInstance, char * lpCmdLine, int nCmdShow) Zeile 804 C++
OGLES3ChameleonMan.exe!__tmainCRTStartup() Zeile 238 C
OGLES3ChameleonMan.exe!WinMainCRTStartup() Zeile 164 C
kernel32.dll!@BaseThreadInitThunk@12() Unbekannt
ntdll.dll!___RtlUserThreadStart@8() Unbekannt
ntdll.dll!__RtlUserThreadStart@8() Unbekannt

I wonder if ATI sometimes “loses” vbo memory handles and forgets to tell the caller.


#7

After several debugging session I can actually confirm that the ati dll is trying to pull vbo data, but the memory where it tries to read is not allocated. Maybe it isn’t detected somewhere if glBufferData fails.


#8

Hi Roger!
Can you attach the full src code and *.vcproj for ChameleonMan Example(without graphics data)?

I can test it, because I have some ATI/AMD cards, such a AMD R7 240,AMD R5 230, and ATI HD5670


#9

Hello Roger,

Sorry for the delay.

We have tested your application on an AMD card as attached.

[attachment file=53412]

We similarly exhausted GPU memory before crashing as on Nvidia.

[attachment file=53411]

Do you mean the memory it tries to read from user mode? Or the memory region it is writing to?

Thanks,
Paul


#10

Ok, here’s my project. I removed all of the content from it:

[attachment file=53415]

It should be enough to copy it over an existing
Imagination/PowerVR_Graphics/PowerVR_SDK/SDK_3.5/Examples/AdvancedChameleonMan

The necessary sln should be in

\Imagination\PowerVR_Graphics\PowerVR_SDK\SDK_3.5\Examples\Advanced\ChameleonMan\OGLES3\Build\WindowsVC2010

I start the Debug configuration.


#11

Note: I think this


atioglxx.dll!68b4de03() Unbekannt
atioglxx.dll!6886f0ce() Unbekannt <<<<<<<<<<<
libGLESv2.dll!0fffd0a7() Unbekannt

may be a call to glGetIntegerv.


#12

Ok, I did another output, this time with glIntercept to get the actual OpenGl calls the emulator creates. It goes from the program start to the moment of the crash:

[attachment file=53492]

Interesting: The address ( 0x06E4803C) the final glDrawElements call unsuccessfully tries to pull the vertex data from resembles a lot this call:

glGetIntegerv(GL_NUM_EXTENSIONS,003C6E48)

Regards


#13

Any ideas?


#14

Hello?


#15

Sorry for the delay in response.

I am not sure as we can’t reproduce the issue with our AMD cards.

Is this a discrete graphics card with it’s own separate memory? Is there any chance you are running out of system memory?

Thanks,
Paul


#16

No, I have 16 GB.

Some news however:

The crash only seems to occur in the glDrawElements caused by the belt component.
It seems to try to access some dynamic memory usually reserved inside the glDrawElements function itself but which is uninitialized o the crashing frame. The program doesn’t crash prematurely if I switch this part

[scode lang=“c#”]{ // Set the vertex attribute offsets
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData);
glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sNormals.nStride, Mesh.sNormals.pData);
glVertexAttribPointer(TANGENT_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sTangents.nStride, Mesh.sTangents.pData);
glVertexAttribPointer(BINORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sBinormals.nStride, Mesh.sBinormals.pData);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData);
glVertexAttribPointer(BONEINDEX_ARRAY, Mesh.sBoneIdx.n, GL_UNSIGNED_BYTE, GL_FALSE, Mesh.sBoneIdx.nStride, Mesh.sBoneIdx.pData);
glVertexAttribPointer(BONEWEIGHT_ARRAY, Mesh.sBoneWeight.n, GL_UNSIGNED_BYTE, GL_TRUE, Mesh.sBoneWeight.nStride, Mesh.sBoneWeight.pData);}[/scode]

to this

[scode lang=“c#”]{ // Set the vertex attribute offsets
glVertexAttribPointer(VERTEX_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sVertex.nStride, Mesh.sVertex.pData);
glVertexAttribPointer(NORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sNormals.nStride, Mesh.sNormals.pData);
glVertexAttribPointer(TANGENT_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sTangents.nStride, Mesh.sTangents.pData);
glVertexAttribPointer(BINORMAL_ARRAY, 3, GL_FLOAT, GL_FALSE, Mesh.sBinormals.nStride, Mesh.sBinormals.pData);
glVertexAttribPointer(TEXCOORD_ARRAY, 2, GL_FLOAT, GL_FALSE, Mesh.psUVW[0].nStride, Mesh.psUVW[0].pData);
glVertexAttribPointer(BONEINDEX_ARRAY, 4, GL_UNSIGNED_BYTE, GL_FALSE, Mesh.sBoneIdx.nStride, Mesh.sBoneIdx.pData);
glVertexAttribPointer(BONEWEIGHT_ARRAY, 4, GL_UNSIGNED_BYTE, GL_TRUE, Mesh.sBoneWeight.nStride, Mesh.sBoneWeight.pData);}[/scode]

However the belt seems to be missing half of its triangles.

Mesh.sBoneIdx.n and Mesh.sBoneWeight.n are both 1 for the belt.

My best guess is that some component doesn’t reserve enough memory when confronted with 1 byte component size glVertexAttribPointer but it doesn’t crash until the application tries to access an uncommited page.


#17

Do you know if there is a pure OpenGL (no EGL) version of the Chameleon Man available?


#18

Hello Roger,

That is a very interesting lead WRT glVertexAttribPointer - we are still investigating to check if there is an issue here.

We don’t have OpenGL implementations of the demos - we use VFrame to achieve this.

Could you clarify what you mean by “No EGL”?

Thanks,
Paul


#19

Hello,

I would like to test if this is an ATI driver or an emulator problem. This is why I would like to test if the problem still occurs if I don’t use the emulator but only opengl32.dll without egl.


#20

You could try other vendors OpenGL ES emulator layers (such as ARM and Qualcomm) note that we do not test with these.

Modification may be required for EGL window setup.