OpenGL: Out of texture memory? - opengl

I'm writing a little game using OpenGL (in Java through JOGL, but I hardly think that matters), and I have lately been getting quite some error reports of people getting OpenGL errors "1285", which seem to indicate "out of memory". I catch this when checking glGetError after having created new textures, which lends me the feeling that I'm running out of texture memory.
However, this surprises me a bit. Isn't OpenGL supposed to manage texture memory for me, swapping textures between the GPU and process memory as necessary? The specifications for glTexImage2D, for sure, does not include any "out of memory" error as any of the possible error conditions.
Is this generally accepted practice for OpenGL drivers in spite of the specifications? Are only some drivers doing this in spite of the specifications? Do I need to take care to delete textures that haven't been used for a while if I catch this error after glTexImage2D? Or am I perhaps seeing something completely else here that OpenGL's error reporting doesn't quite concisely convey to me?
Edit: For further information, I cannot, unfortunately, debug the problem myself, because I'm not getting it. Reading from the reports people send me, the vast majority of those afflicted by this appear to be using Intel cards, but I've spotted a few nVidia cards as well (even a 680).

It's only a guess, but your program may suffer from address space fragmentation. And if that is the case it indeed matters, that you're running in a Java runtime.
OpenGL, namely the implementation, must keep copies of all data objects, so that it can swap them out on demand. But those copies, they need address space of your process. And if your process environment does a lot of allocations/deallocations, which is the very nature of Java (creating an object for just about everything) it can happen that your address space gets fragmented to the point, that larger chucks can not longer be allocated.
A few points to check: Is your program running on a 32 bit or a 64 bit JRE. If it's a 32 bit executable, try out what happens if you use a 64 bit JRE. If the issues vanish in a 64 bit environment, while on the same machine in a 32 bit environment they are there, it's a address space fragmentation issue for sure.

Related

Converting a 32bit directx9 app to be large address aware

We are running into issues with an old closed-source game engine failing to compile shaders when memory nears 2GB.
The issue is usually with D3DXCreateEffect. Usually it returns HResult "out of memory", sometimes d3dx9_25.dll prints random errors in a popup, or it just outright segfault.
I believe the issue is lack of Large Address Awareness: I noticed one of the d3dx9_25.dll crashes doing something that would hint as such. It took a valid pointer that looked like 0x8xxxxxx3, checked that bits 0x80000003 are lit and if yes, it bit inverts the pointer and derefs it. The resulting pointer pointed to unallocated memory. Forcing the engine to malloc 2GB before compilation makes the shaders fail to compile every time.
Unfortunately our knowledge of DX9 is very limited, I've seen that DX9 has a flag D3DXCONSTTABLE_LARGEADDRESSAWARE but I'm not sure where exactly Its supposed to go. The only API call the game uses that I can find relies on it is D3DXGetShaderConstantTable, but the issues happen before it is ever called. Injecting the flag (1 << 17) = 0x20000 to D3DXCreateEffect makes the shader fail compilation in another way.
Is D3DXCreateEffect supposed to accept the Large Address Aware flag? I found a wine test using it, but digging into DX9 assembly, the error it throws is caused by an internal function returning HResult Invalid Call when any bit out of FFFFF800 in flags is set, which leads me to believe CreateEffect is not supposed to accept this flag.
Is there anywhere else I should be injecting the Large Address Aware flag before this? I understand that a call to D3DXGetShaderConstantTable will need to be fixed to use D3DXGetShaderConstantTableEx, but its not even reached yet.
LargeAddressAware is a bit of a hack, so it may or may not help your case. It really only helps if your application needs a little more room close to 2GB of VA, not if if needs a lot more.
A key problem with the legacy DirectX SDK Direct3D 9 era effects system is that it assumed the high-bit of the effect "handle" was free so it could use it, and without the bit the handle was an address to a string. This assumption is not true for LargeAddressAware.
To enable this, you define D3DXFX_LARGEADDRESS_HANDLE before including d3dx9.h headers. You then must use the D3DXFX_LARGEADDRESSAWARE flag when creating all effects. You must also not use the alias trick where you can use a "string name" instead of a "handle" on all the effect methods. Instead you have to use GetParameterByName to get the handle and use that instead.
What I can't remember is when the LAA flag was added to Effects for Direct3D 9.
If you are using d3dx9_25.dll then that's the April 2005 release of the DirectX SDK. If you are using "Pixel Shader Model 1.x" then you can't use any version newer than d3dx9_31.dll (October 2006)--later versions of the DirectX SDK let you use D3DXSHADER_USE_LEGACY_D3DX9_31_DLL which just passed through shader compilation to the older version for this scenario.
A key reason that many 32-bit games would fail and then work with LAA enabled was because of virtual memory fragmentation. Improving your VA memory layout can making your allocations more uniform can help too.
The issue we were having with CreateEffect not accepting the LargeAddressAware flag is pretty obvious in hindsight, the dx9 version the engine is using (d3dx9_25.dll) simply did not have this feature yet.
Our options, other than optimizing our memory usage are:
Convert all our pixel shaders 1.x to 2.0 and force the engine to load a newer version of d3dx9, hope the engine is not relying on bugs of d3dx9_25.dll or the alias trick, then inject the LargeAddressAware flag bit there.
Wrap malloc, either avoiding giving handles large addresses (I am unsure if this is also required inside the dll as well) or stick enough other data in large addresses so dx9 related mallocs don't reach it.

OpenGL not throwing error and not showing difference in memory allocation for large 3D textures

I am allocating a large 3D texture and seeing differences in program output, I suspect these differences to be caused by the system not having enough memory for the texture, but I am not sure how to verify and dynamically correct the issue.
The texture is allocated as:
glTexImage3D(GL_TEXTURE_3D, 0, GL_RGBA32F, side, side, side, 0, GL_RGBA, GL_FLOAT, NULL);
When side is 512 the program works, when it is 1024 it doesn't.
However glGetError returns GL_NO_ERROR for both values.
In addition to that
glGetIntegerv(GL_GPU_MEMORY_INFO_CURRENT_AVAILABLE_VIDMEM_NVX,&x);
returns 7729 MB available out of 8192 regardless of the value of size.
Moreover calling glGetIntegerv(GL_MAX_TEXTURE_SIZE, temp*) tells me that the maximum texture side is supposed to be 32768 (although I know that is for 2D textures and it probably does not apply to 3D textures).
I want to have the system crash or otherwise report to me that I am trying to allocate too much memory, or at least have a way to check myself if this is the case, alas none of the methods that I have been suggested seem to work.
Update:
I have played around with stuff and found things that I am not happy with. First, I am able to get an out of memory error if I allocate textures that are large enough.
So my program has the following behavior:
-Small textures work
-Medium textures do not work and do not report errors
-Large textures do not work and report errors
I can't accept this, I need there to be only textures that work or textures that do not work and warn me about it, I cannot have textures that don't work without ever raising flags or issues.
Second, the treshohold for working vs not working fluctuates over time on the same machine independently of program execution.
So I ran the program a good chunk of times found a working vs not working threshold, then closed it and read some documentation, launched it again, and the treshold changed (so the threshold is stable across multiple program instances for a small period but not stable on the same machine over a long period). This has happened multiple times already. The working point is the same for multiple program launches when those instances are close to each other in time, but not if they are far away in time.
Checking memory using the nvidia extension results in the exam same code, so I have no reliable way of detecting when I have messed up.
TL;DR
I just want to know that I have messed up, it can be after the fact, I just want to eventually be told that my texture is too big and OpenGL failed to create the texture, I can't believe that there is no way to check for this, there has to be a way to someow detect that a texture is not working other than inspecting visual output.
The enumerator GL_MAX_3D_TEXTURE_SIZE defines how big 3D textures can be, and 4.6 implementations are required to support at least 2048 per dimension.
Of course, this says nothing about memory limitations.
OpenGL implementations are not required to fulfill the execution of any function immediately (unless the function specifically says it does). They can defer things like memory allocation until whenever they like. As such, the error GL_OUT_OF_MEMORY can be thrown at any time, regardless of when the operation that actually runs out of memory was executed.
I just want to be told when I am trying to do something the system can't handle.
This is why Vulkan exists; OpenGL is simply not equipped to answer those questions immediately.

Does OpenGL takes care of GPU memory fragmentation?

So basically whenever I create buffer objects Opengl allocates some memory on the GPU.
Consider scenario 1 where I generate 2 uniform buffers for 2 uniform variables.
Now consider scenario 2 where I create a single buffer and enclose the 2 uniform variables inside an interface block.
My understanding is that for scenario 1, two separate regions of memory get allocate while for scenario 2, one big contiguous block of memory gets allocated. If so, then Scenario 1 might be susceptible to memory fragmentation and if this happens is it managed by OpenGL or something else OR should we keep this in mind before writing performance critical code?
Actually I have to fix that for you. It's
So basically whenever I create buffer objects Opengl allocates some memory.
You don't know – and it's invalid to make assumptions – about the whereabouts of where this memory is located. You just get the assurance that it's there (somewhere) and that you can make use of it.
managed by OpenGL or something
Yes. In fact, and reasonable OpenGL implementations do have to move around data on a regular basis. Think about it: On a modern computer system several applications do use the GPU in parallel, and neither process (usually) does care about or respect the inner working of the other processes that coinhabit the same machine. Yet the user (naturally) expects, that all processes will "just work" independent of the situation.
The GPU drivers do a lot of data pushing in the background, moving stuff between the system memory, the GPU memory or even swap space on storage devices without processes noticing any of that.
OR should we keep this in mind before writing performance critical code?
Average-joe-programmer will get the best performance by just using the OpenGL API in a straightforward way, without trying to outsmart the implementation. Every OpenGL implementation (= combination of GPU model + driver version) has "fast paths", however short of having access to intimately detailed knowledge about the GPU and driver details those are very difficult to hit.
Usually only the GPU makers themselves have this knowledge; if you're a AAA game studio, you're usually having a few GPU vendor guys on quick dial to come for a visit to your office and do their voodoo; most people visiting this site probably don't.

OpenGL: Crashes at random OpenGL function call

I am getting weird problem, the crash happens at random times, for example i managed to use the 3d app for a while without crashing, then most of the times it crashes always when i suddenly render a lot of objects at same time.
I have recently noticed that changing the huge texture surface on this ATI card will crash my whole computer when using huge texture sizes and a lot of them and switching from one to another in one frame. So it is a possibility i have broken ATI card or just buggy one. But it is imporobable since i've added some code lately and now i have noticed this crash first time. I didnt use any special opengl calls, just the good old glbegin() glend() glcolor() etc...
If i comment out the line where it crashed previously, for example glBegin(GL_QUADS) ... glEnd() Then next time i get crash on different openGL function call at different place of my code, for example glColor4f() and then i comment that out, and the next crash i get at glClear() at totally different part of the rendering code!
What could be causing these? Im using ATI card, and i am aware some opengl calls may crash the program if they are using improper values, like glLineWidth(4) will crash some ATI cards on a random line of openGL code because the max line width is 3!
Edit:
When i run the program in debug mode with ApplicationVerifier, it throws me this line:
if(!(PixelFormat = ChoosePixelFormat(hDC, &pfd))){
I dont understand, what could possibly be wrong on it?
pfd:
static PIXELFORMATDESCRIPTOR pfd = {
// *correct amount of elements*
};
IMO, chances are pretty good that the crash in OpenGL is only a symptom, and the real problem lies elsewhere. In general, your description sounds more or less typical for resource misuse (e.g., memory leakage, using a dangling pointer, trashing the heap, etc.)
Something like a driver bug is certainly possible -- in fact a graphics driver is big and complex enough that some bugs are probably almost inevitable. The obvious test for that would be to run other code that uses OpenGL and see if it works dependably. It's always possible that you're using an execution path that contains a bug, but is so obscure almost nothing else uses it so the bug isn't otherwise triggered -- but given that the crash isn't happening in a fixed location, that seems fairly unlikely (still possible, just unlikely). If a graphics driver has a bug (especially one serious enough to cause crashes, not just mis-rendering), it usually becomes known pretty quickly.
Such random behaviour is usually the symptom of a stack/heap corruption. You should check that you're not corrupting the heap and/or the stack. Buggy drivers is also a option, since crashing on a invalid value is a bug, that should not crash and instead produce a GL error.

Boggling Direct3D9 dynamic vertex buffer Lock crash/post-lock failure on Intel GMA X3100

For starters I'm a fairly seasoned graphics programmer but as wel all know, everyone makes mistakes. Unfortunately the codebase is a bit too large to start throwing sensible snippets here and re-creating the whole situation in an isolated CPP/codebase is too tall an order -- for which I am sorry, do not have the time. I'll do my best to explain.
B.t.w, I will of course supply specific pieces of code if someone wonders how I'm handling this-or-that!
As with all resources in the D3DPOOL_DEFAULT pool, when the device context is taken away from you you'll sooner or later will have to reset your resources. I've built a mechanism to handle this for all relevant resources that's been working for years; but that fact nothingwithstanding I've of course checked, asserted and doubted any assumption since this bug came to light.
What happens is as follows: I have a rather large dynamic vertex buffer, exact size 18874368 bytes. This buffer is locked (and discarded fully using the D3DLOCK_DISCARD flag) each frame prior to generating dynamic geometry (isosurface-related, f.y.i) to it. This works fine, until, of course, I start to reset. It might take 1 time, it might take 2 or it might take 5 resets to set off a bug that causes an access violation either on the pointer returned by the Lock() operation on the renewed resource or a plain crash -- regarding a somewhat similar address, but without the offset that it has tacked on to it in the first case because in that case we're somewhere halfway writing -- iside the D3D9 dll Lock() call.
I've tested this on other hardware, upgraded my GMA X3100 drivers (using a MacBook with BootCamp) to the latest ones, but I can't reproduce it on any other machine and I'm at a loss about what's wrong here. I have tried to reproduce a similar situation with a similar buffer (I've got a large scratch pad of the same type I filled with quads) and beyond a certain amount of bytes it started to behave likewise.
I'm not asking for a solution here but I'm very interested if there are other developers here who have battled with the same foe or maybe some who can point me in some insightful direction, maybe ask some questions that might shed a light on what I may or may not be overlooking.
Thanks and any corrections are more than welcome.
Niels
p.s - A friend of mine raised the valid point that it is a huge buffer for onboard video RAM and it's being at least double or triple buffered internally due to it's dynamic nature. On the other hand, the debug output (D3D9 debug DLL + max. warning output) remains silent.
p.s 2 - Had it tested on more machines and still works -- it's probably a matter of circumstance: the huge dynamic, internally double/trippled buffered buffer, not a lot of memory and drivers that don't complain when they should..
p.s 3 - Just got told (should've known) that the Lock and Unlock do a full copy of the 18MB -- that's not too smart either, but still :) (I do use that saner strategy for the renderer's generic dynamic VB/IBs).
Unless someone has a better suggestion; I'd still love to hear it :)