Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to handle GL_OUT_OF_MEMORY error during glBufferData?

Tags:

opengl

The OpenGL reference mentions about the GL_OUT_OF_MEMORY error

The state of the GL is undefined, except for the state of the error flags, after this error is recorded.

The function glBufferData can generate this error if it can't digest the given data. But on the other hand the API doesn't seem to provide any way to check if sending data of particular size would succeed.

Is this situation really hopeless? If I get this error, is the only thing left for me to recreate the whole OpenGL context and start over?

like image 281
Marcin Kaczmarek Avatar asked Dec 01 '22 17:12

Marcin Kaczmarek


1 Answers

What do you do if malloc returns NULL or new throws an exception? Do you have a recovery path for that possibility?

Most applications don't. Most applications happily assume that malloc will never return NULL and/or that new will never throw. And if those operations fail, they will happily crash.

The same would generally go for OpenGL. You presumably asked for that particular memory size for a good reason; because you needed it. And if you can't get it, for whatever reason, there usually isn't a solution for that.

While there are cases where you could recover from not being able to allocate memory, OpenGL confounds you in another way.

See, the reason that the entire state of OpenGL is undefined on an OUT_OF_MEMORY error is this: OOM can happen from anywhere. No function's documentation claims that it can issue an OOM error because every function can issue such an error.

Memory is not (necessarily) allocated when you call an allocating function. The driver can (and almost certainly will) defer allocation until later. So you get an OOM error from whatever OpenGL function you call after the driver detects the OOM condition.

So if buffer allocation fails, long after the call to glBufferData that provoked the failure, what can the OpenGL specification say about the current state? From the OOM error alone, there is no way to track down exactly what caused it.

So if you get this error, recovery is not really possible. Your only real recourse is to terminate the application or rebuild it.

Note that lower-level APIs like Vulkan or D3D12 will OOM immediately when you try to allocate memory and cannot.

Also:

But on the other hand the API doesn't seem to provide any way to check if sending data of particular size would succeed.

That would solve nothing. Why?

Because your application doesn't own the GPU; your OS does. Multiple programs can allocate memory on the GPU at the same time. The OS can poke about with memory too, paging things into and outof memory as it sees fit.

So if you ask if an allocation would succeed, and OpenGL returned yes, by the time you actually perform that allocation, the answer may have changed.

This is also why Vulkan and similar APIs do not have a function to test if an allocation will succeed (nor does it have a function to test how much memory is left unallocated). You just allocate memory; either it works and you get your memory, or it fails and you don't.

like image 184
Nicol Bolas Avatar answered Dec 07 '22 23:12

Nicol Bolas