Skip to main content
GameDev.net gamedev.net
🔒 Locked

Knowing video card limits- memory caching

Started by okonomiyaki Aug 13, 2004 at 8:09 AM 13 replies 9.7k views
Original Post
okonomiyaki
okonomiyaki
I have found serveral good pages and threads about how to manage memory on the video card (and even adapt those techniques to managing RAM), but I haven't found anyone mention how they determine how much memory to manage. Lets just say a simple slot structure, where you have slots of 512k memory. For a 32meg video card, you could allocate x number of these slots. But for a 256meg video card, you could allocate 8x of these slots. It seems like some people just always allocate x number of slots, and if the video card has room for it, then great. If it doesn't, then it will fall back to system memory itself. But that seems to be the worst idea, when all you have to do is take memory management a step further and handle swapping yourself! It would be very to easy to say, all of the slots are full on this card, delete one, and then upload the new data. Obviously with lower memory cards, more swapping would go on, but that's obvious, and it would happen transparently anyway. That way, you know exactly where everything is in memory. You could also adapt it to RAM, instead of letting the system swap things on virtual RAM, allocate enough memory that's sure to be held in RAM, and swap against the HDD yourself when the blocks start getting full. Now to my main question: to do this, I have to be able to query the size of the video card's ram. How do I do this? I'm using OpenGL. I've been able to query the system ram. Or is there a reason why I haven't heard it mentioned? Probably because it was obvious- but I still can't figure out how to query how much vram I have to work with. Thanks!
illadel4life
illadel4life
I know you said OpenGL but I know on DirectX there is a D3DCapp function, and it lets you know the cappabilites of the hardware its running on. Heres a thought, Mabye make a D3D object just to get the Capabilites and then run u'r app with OpenGL using the info you got from D3D?? I warn you though I don't know exactly what the D3Dcapp returns even if its the actually Ram itself or like what pixel shader version, hey if it tells what type of card, create a table/ small database and there ya go!
okonomiyaki
okonomiyaki
There is glGetString(GL_RENDERER) that returns the name of the card. I don't think it has any vram specs in it though.
The table is an idea, but one card can come with different of options of vram. So I'm not sure how I would detect that.
And I'm trying to keep cross-compatibility, so I hate to instantiate DX just for this!

Still though, I'm kind of confused. Should I not do this? Why aren't there others out there doing it?
CoffeeMug
CoffeeMug
You could try allocating a very large cache. If you get an error, try a smaller one. If you get an error again, try a smaller one yet again. Continue until the allocation succeeds.
okonomiyaki
okonomiyaki
I thought about doing something like that, but I'll be using VBO's. It seems that you can't allocate a VBO larger than 32 megs. But, you can allocate multiple VBO's of 32 megs each, but it will eventually fall into system RAM, and I have no idea when it does that :(

I always wondered why the extension spec said that a VBO allocation will return OUT_OF_MEMORY if it's too large, and yet it is supposed to fall back to system ram if it runs out. After testing, a VBO returns OUT_OF_MEMORY if you allocate anything larger than 32 megs with one buffer. But, in terms of several smaller buffers, the allocation succeeds and falls back to system ram when it *actually* runs out of memory (I think that error value is misleading in this case).

I think 32 megs is a hardcoded cap, not video card dependant. So internally, I still don't know when it falls back to system ram. (ok I'm repeating myself now.)

It's a good suggestion though! But from my understanding, I don't know how it would work.

edit: I suppose I could set a variable for the size to use. I could just let the user, in setup, select the size of his memory card. By default I could use assume a standard size, such as 128megs, but this could lead to innaccurate cache swapping if he/she has a different card and they don't know to change the setting.
Yann L
Yann L
It's quite risky to determine available memory by using "VBO size probing". Keep in mind that VRAM is a shared resource, and vertex/index data is not the only type of data stored there: framebuffer, textures, pbuffers, display lists, etc. Imagine the following situation: you probe available memory after creating the framebuffer, but before textures are loaded and/or pbuffers are created. Note that you can't control the point where those resources are loaded into VRAM, the driver decides. Even if you submitted all textures to OpenGL using glTexImage, there is no guarantee that they were uploaded to VRAM yet (most probably not). So, if your probe returns a very large amount of free memory (because VRAM is still unused at that point), you'll allocate a large chunk for your VBOs. But as soon as you start rendering, not enough space is available to load your textures. As a result, the driver will start swapping in and out, while your huge VBO chunk is a major inconvenience, as it can only be swapped as a continuous block. You'll lose a lot of performance in that scenario.

The bottomline is that you can't get the exact amount of available memory, and you shouldn't care about it either. Just make your VBO cache size a user setting. Then check the vendor string to preselect an approximate setting (eg. 8MB on a GF2, 16MB on a GF3/4, 32MB on a GFFX). Let the user adjust and finetune as needed.

Oh, and forget about this "use D3D caps to determine the available memory for OpenGL" idea. That will result in 100% undefined behaviour.
okonomiyaki
okonomiyaki
Yann, I agree. I wasn't going to do that! I didn't really like the idea of querying the vram with VBO allocation, because as you said I have no idea what's really free. I didn't want to know how much vram was free anyway, but how much there was total. If I knew I was dealing with a 128meg card, I knew I could dedicate 32 megs or so to geometry, etc. But your right, I've realized I'll just have to make it a user setting and try to approximate it.
Thanks a lot.
illadel4life
illadel4life
Hold on though, Run a D3DX sample from the SDK, if you notice it tells you exactly your Video card and possibly the ram (I might be mistaken). Not saying Use D3D capps and import it in OpenGL, but to use D3D capps and extract some data(store something in an int), release it and be on your way. Besides thats the purpose of DirectX is to find out what the user has, and what the user doesn't have and emulate what the hardware can't do. In order todo that it has to have access to the hardware. Maybe D3D capps my not be the "right" way but it finds out some how, maybe look into some interface coding and ask the board directly, don't give up so easily!
Sr_Guapo
Sr_Guapo
So OGL doesn't have any kind of query interface for cards like DX? That seems weird. Are there any free multiplatform APIs that you can use?
Sean Henley [C++ Tutor]Rensselaer Polytechnic Institute
CodeMunkie
CodeMunkie
Quote:
Original post by illadel4life
Hold on though, Run a D3DX sample from the SDK, if you notice it tells you exactly your Video card and possibly the ram (I might be mistaken). Not saying Use D3D capps and import it in OpenGL, but to use D3D capps and extract some data(store something in an int), release it and be on your way. Besides thats the purpose of DirectX is to find out what the user has, and what the user doesn't have and emulate what the hardware can't do. In order todo that it has to have access to the hardware. Maybe D3D capps my not be the "right" way but it finds out some how, maybe look into some interface coding and ask the board directly, don't give up so easily!


If you read the docs you will notice that the returned value is an estimate and you should not rely on it to make the types of decisions that the OP is trying to make:
Quote:

The returned value is rounded to the nearest MB. This is done to reflect the fact that video memory estimates are never precise due to alignment and other issues that affect consumption by certain resources. Applications can use this value to make gross estimates of memory availability to make large-scale resource decisions such as how many levels of a mipmap to attempt to allocate, but applications cannot use this value to make small-scale decisions such as if there is enough memory left to allocate another resource.


Think about it and this makes sense. You don't talk directly to the video card, you talk to the driver. When you call a DirectX or OpenGL function you merely make a request to the driver to move some data. It is the driver's responsibility to figure out where that data should go. That could be system, agp, or video memory. The point is, you don't know where it puts the data, nor should you be concerned. So there is no reason for you to query the card for this value. Simply scale your data sets based on user input (low, medium, high quality) or based on the vendor string as Yann suggested. Look at Doom 3 and many other modern games that do just this.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
CodeMunkie
CodeMunkie
Quote:
Original post by Sr_Guapo
So OGL doesn't have any kind of query interface for cards like DX? That seems weird. Are there any free multiplatform APIs that you can use?


Sure it does. OpenGL just uses a different mechanism but it accomplishes the same thing. In OpenGL you attempt to aquire pointers to the extension function that does what you want. If the function comes back NULL, then that functionality does not exist in the driver.
"When you die, if you get a choice between going to regular heaven or pie heaven, choose pie heaven. It might be a trick, but if it's not, mmmmmmm, boy."
How to Ask Questions the Smart Way.
EvilDecl81
EvilDecl81
Quote:


Or is there a reason why I haven't heard it mentioned? Probably because it was obvious- but I still can't figure out how to query how much vram I have to work with. Thanks!


Knowing how much memory is available isn't going to be incredibally useful since you do not have any control over how it is allocated.

Alot of things can be stored in video memory, and sometimes a resoures which appears to be relatively small, might expand to more memory then you expect. Additionally, video memory can become fragmented, eventually causing allocations to fail even though there are resources available.

If you are using D3D, then you can elect to manuelly allocate resources on the video card - you can keep creating them until something fails - then chose to evict something etc. This is a somewhat complex procedure, however, and you are the mercy of the driver's memory allocater. You get more abitious and create a static set of resources known to be on the video card and manuelly copy memory in and out of them... but this would take alot of work ;)

The most common solution is to build up a profile set for a certain video card and memory configuration. Many games literally have a database of 100s of configurations which have been pretested and they chose based on that. They then scale back content accordingly.


EvilDecl81
Zelex
Zelex
I'm at QuakeCon right now, but when I get back I'll post some code to find the amount of memory that is on a video card. Its disturbing how many hoops you have to jump through just to find it. But it can be done. :)
-- Jon Olick
Zelex
Zelex
Quote:

The way I do this is to create a DX7 Directdraw interface, and use
GetAvailableVidMem. You need to call it with a wide variety of flags, since
different drivers add AGP memory at random times, even when they're not
meant to. So call it with the following selections:

DDSCAPS_3DDEVICE | DDSCAPS_LOCALVIDMEM | DDSCAPS_TEXTURE |
DDSCAPS_VIDEOMEMORY

(some devices return 0 because they can't render to texture, so ignore those
returns)

DDSCAPS_LOCALVIDMEM | DDSCAPS_TEXTURE | DDSCAPS_VIDEOMEMORY

(some devices include AGP memory even though you have set the LOCALVIDMEM
flag)

DDSCAPS_OFFSCREENPLAIN | DDSCAPS_LOCALVIDMEM | DDSCAPS_VIDEOMEMORY


So, ignore any 0 results, and take the minimum value of all of these, which
will weed out the ones that include AGP memory. This should give you the
total amount of actual on-card video memory.

Note - you need to specially detect and deal with the Voodoo1 and 2 of
course, since they have separate video and FB memory. But they have known
DeviceIDs, so you can relaibly detect them.
-- Jon Olick
okonomiyaki
okonomiyaki
Seems complicated, and unsafe?
Even if that works most of the time, if I depend on that, all it does is open up major bugs later on when testing on a wide variety of machines.
Not to mention the fact that I definitely don't want to instantiate DX just for this.

I appreciate your suggestion, but I'm fine with approximating it and letting the user fine tune it :)

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.