views:

355

answers:

4
+7  Q: 

Shader limitations

I've been tuning my game's renderer for my laptop, which has a Radeon HD 3850. This chip has a decent amount of processing power, but rather limited memory bandwidth, so I've been trying to move more shader work into fewer passes.

Previously, I was using a simple multipass model:

  • Bind and clear FP16 blend buffer (with depth buffer)
    • Depth-only pass
    • For each light, do an additive light pass
  • Bind backbuffer, use blend buffer as a texture
    • Tone mapping pass

In an attempt to improve the performance of this method, I wrote a new rendering path that counts the number and type of lights to dynamically build custom GLSL shaders. These shaders accept all light parameters as uniforms and do all lighting in a single pass. I was expecting to run into some kind of limit, so I tested it first with one light. Then three. Then twenty-one, with no errors or artifacts, and with great performance. This leads me to my actual questions:

Is the maximum number of uniforms retrievable?

Is this method viable on older hardware, or are uniforms much more limited?

If I push it too far, at what point will I get an error? Shader compilation? Program linking? Using the program?

A: 

I guess the maximum number of uniforms is determined by the amount of video memory, as it's just a variable. Normal varaibles on the cpu are limited by your RAM too right?

Brammie
Uniforms have a strict limit set by the hardware. Modern hardware has very high limits but they still exist. Older hardware (2+ years) may have much lower limits.
Ron Warholic
+5  A: 

Shader uniforms are typically implemented by the hardware as registers (or sometimes by patching the values into shader microcode directly, e.g. nVidia fragment shaders). The limit is therefore highly implementation dependent.

You can retrieve the maximums by querying GL_MAX_VERTEX_UNIFORM_COMPONENTS_ARB and GL_MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB for vertex and fragment shaders respectively.

moonshadow
Note that for GL2.0 you're guaranteed to have at least 512 vertex uniforms and 64 fragment uniforms.
Ron Warholic
Oh, failure to RTFM on my part.More questions come to mind:Do floats and ints each consume one component?Are there any restrictions on packing? Four floats versus one vec4? One float and one vec3?
mvanbem
@mvanbem: One uniform takes up at least one 4D vector. So if you are really tight on uniform storage, consider packing multiple scalars into one 4D vector.
Mads Elvheim
+2  A: 

See 4.3.5 Uniform of The OpenGL® Shading Language specs:

There is an implementation dependent limit on the amount of storage for uniforms that can be used for each type of shader and if this is exceeded it will cause a compile-time or link-time error. Uniform variables that are declared but not used do not count against this limit.

It will fail at link or compile-time, but not using the program.

Stringer Bell
+1  A: 

For how to get the max number supported by your OpenGL implementation, see moonshadow's answer.

For an idea of where the limit actually is for arbitrary GPUs, I'd recommend looking at which DX version that GPU supports.

DX9 level hardware:

  • vs2_0 supports 256 vec4. ps2_0 supports 32 vec4.
  • vs3_0 is 256 vec4, ps3_0 is 224 vec4.

DX10 level hardware:

vs4_0/ps4_0 is a minumum of 4096 constants per constant buffer - and you can have 16 of them.

In short, It's unlikely you'll run out with anything that is DX10 based.

Bahbar