Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

gDEbugger states that OpenGL's program objects only occupy an insignificant amount of memory. How much is this actually? I don't know if the stuff I looked up in mesa is actually that I was looking for but it requires 16KB [Edit: false, confusing struct names, less than 1KB immediate, some further behind pointers] per program object. Not quite insignificant.

So is it recommended to create a unique program object for each object of the scene? Or to share a single program object and set the scene's object's custom variables just before its draw call?

share|improve this question
    
Is that a GLSL program, or..? What is the meaning in your context of the idiom "program object" for "each object of the scene". Are you talking about object instances, glsl programs or about .obj files? –  teodron Aug 8 '12 at 19:27
1  
Yes, GLSL. "Program object" is the type of object you create using glCreateProgram and attach shaders to and maybe set uniforms and so on. "Object of the scene" is a collection of program object, textures, vertex buffers that are used to configure the pipeline before a draw (glDraw*) some entity. –  Hans Wurst Aug 8 '12 at 19:54
    
Is it recommended to create for each "object of the scene" a unique "program object" and make it manage the "object of the scene's" unique uniforms? Or do I share a "program object" and keep a map of uniforms for each "object of the scene" and repeatedly apply each "object of the scene's" uniforms to the "program object" quite before glDraw*. –  Hans Wurst Aug 8 '12 at 19:57
    
Quite a good question!! I tend to divide things like this, when it comes to uniforms: keep a list/map of global uniforms (uniforms that are scene specific - e.g. lights) and a map of uniforms that are object specific (as a member of your object class). For programs, of course, use a program manager.. –  teodron Aug 8 '12 at 20:34
add comment

3 Answers 3

An OpenGL program consists of at least a vertex and a fragment shader that are compiled and linked. Once you want to use a program, you must link it. You can create a program manager/shader manager/material manager (call it however you want, equip it with whatever functionality you need). This program manager keeps a map of all vertex-fragment shader pairs that do appear in the materials your objects use. You should group your objects by program and not recompile-relink the program each time you draw an object. You can use the program manager to check whether a certain program is the active one. That active program will be responsible for the shading of any object that issues render calls.

Now, the attributes and uniforms need their own managers. Usually, keeping maps to manage them is a good idea. For uniforms, you could keep two kind of maps:

  • a global uniforms map that stores data that's scene specific (specific to all or most objects in a scene, perhaps to some objects groups). They represent data such as lights, environment/weather factors, etc. An object has an associated program. That program will query the global uniforms for the existence of a certain variable and try to get its value from that global map of uniforms. If it cannot find it, then maybe that uniform is object specific.
  • an object uniforms map that stores data which is local and accompanies an object instance. For example, you have some cars in your scene, each having an uniform called "reflectivity". That uniform is car specific, one care is more matte than the others, etc.. You get your uniform value by querying the object's uniforms map whenever a certain program is active and does require a value for an uniform.

If an active program cannot find an uniform in neither places, you should decide whether you supply default values in the program/material file or if you somehow forbid such a possibility by throwing exceptions.

share|improve this answer
add comment

1k (or even 16k) is actually an incredibly insignificant amount for modern GPU memory sizes - a 512x512 RGBA texture (which you would likely use on many objects) weighs in at over 750k, by comparison.

I think you're confusing how you should create program objects though. There's no way you'd create one for each scene object; instead you create one for each object type, or material type, and reuse it where possible. This is not so much to do with memory saving as it is to do with reducing shader changes (which can be a very expensive operation).

Going back to the texture comparison I made, it's much the same thing. You don't have a separate set of textures for each object, you have a single set of textures which get shared by multiple objects. Same deal with shaders.

Despite that, many modern (or not so modern) games easily end up with hundreds of shaders, so you can see that it's not that big a deal.

share|improve this answer
add comment

So is it recommended to create a unique program object for each object of the scene? Or to share a single program object and set the scene's object's custom variables just before its draw call?

No, but not for reasons of memory consumption.

The only reason you would have for creating a program for every object would be to avoid uniform changes. Now consider the fact that pretty much every program that uses GLSL, or even Direct3D, has uniform changes as part of what is needed to render other stuff.

In short: you don't need it. Especially not nowadays with uniform buffers and the like to make changing global uniforms pretty simple.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.