Managing video memory when objects' lifetime isn't known.

Started by
1 comment, last by tactical_salamander 10 years, 10 months ago

Hello, Gamedev. I'm a long-time lurker, first time poster.

Recently, I've been working on a graphics engine as a hobby. One of the things I would like to be able to do, if only to experiment, is dynamically stream in meshes to the graphics card as needed. Consider a game like one of the newer Grand Theft Auto games, where there are gigabytes of complex meshes for objects like cars, but at any given moment only a couple hundred are in memory.

Since I don't know the lifetime of any of the game objects a priori (it depends on where the player is and what they're doing), I need form of memory manager for the video memory objects. I could probably write a simple linked-list based heap or something, but I hesitate to do so before learning about other solutions to this problem, especially since free-roaming games are becoming increasingly popular and this may well be a solved problem.

Strangely, I have been unable to find any information about this issue. Most of the articles I've found just statically allocate the vertex buffers and load everything at once, but this is not suitable when the size of the assets exceeds video memory. The simplest solution I can think of is to assign a vertex buffer to each mesh, because then the video driver will manage the memory for me. I have heard that doing this can be slow, however.

Thanks in advance for providing any suggestions or experience. I am working in OpenGL currently, if it matters.

Advertisement

I think that with mobile/desktop OpenGL your simplest approach is to let the drivers deal with the details at the lower level, and you just control which lods of which models/textures are loaded at any given time, and you do some housekeeping to ensure that you're not overloading the video memory too much at any time.

I suppose you could try to preallocate pools of fixed sized vertex buffers and fixed sized texture assets and dynamically load data in and out of them, but I'm just not sure that gains you much.

On consoles you generally get full control of the video memory allocation strategy, and that's where things get interesting. Broadly, if you're on a system that lets you fully manage video memory yourself you have two main options, both of which have merits and are perfectly viable options used in shipped games:

1. Use pools of fixed sized blocks to limit fragmentation. This is simple and means you can give clear budgets to artists.

2. Leave a chunk of memory unused (25% perhaps), and have the system continuously move assets around to defragment. 25% sounds like a lot of memory to leave on the table, but the pool approach will likely waste just as much if not more from having fixed sized blocks that don't fit tightly.

This slightly dated, but excellent article gives you an idea of some of the challenges of doing open world streaming : http://www.clarets.org/steve/work/Memory%20debugging%20on%2024.html.

That article is a fantastic read! Thank you!

On consoles you generally get full control of the video memory allocation strategy, and that's where things get interesting. Broadly, if you're on a system that lets you fully manage video memory yourself you have two main options, both of which have merits and are perfectly viable options used in shipped games:

Unfortunately I'm on the PC. I hope that someday, PCs will be able to have a unified memory architecture like the current batch of next gen consoles.

1. Use pools of fixed sized blocks to limit fragmentation. This is simple and means you can give clear budgets to artists.

2. Leave a chunk of memory unused (25% perhaps), and have the system continuously move assets around to defragment. 25% sounds like a lot of memory to leave on the table, but the pool approach will likely waste just as much if not more from having fixed sized blocks that don't fit tightly.

This makes a lot of sense. I can still use a system like this even without complete memory management access, if I have one giant vertex buffer divided logically into 4k chunks for example, with a bitmap to see what's allocated.

Also I just read that the cost to set the active vertex buffer is fairly minimal, so maybe it was a bit foolish of me to immediately start thinking about optimizing. I had assumed that the cost to bind a vertex buffer was on the same order of magnitude as the cost to bind a texture, but after some further testing it seems to be much faster.

I wish there was a giant test database of different video cards and how long they take to complete certain OpenGL commands.

This topic is closed to new replies.

Advertisement