Performance; Shader parameter passing in an efficient way

Started by
7 comments, last by MJP 12 years, 3 months ago
Trying to improve performance, and yet another pain in the ass are shader parameters (using Cg here btw). Although I already try to sort on material as much as possible, there are still hundreds of vectors and textures
passed each cycle, giving quite a serious hit. Pretty much every material has a couple of parameters, a typical example would be:

sampler2D albedoMap
sampler2D normalMap
float4 specularColor_andShininessFactor
float4 ReflectivityParameters
float3 somethingElse_DependingOnChosenShader

And, pretty much all shaders also refer to common variables such as the current camera position.


Now I don't know how to decrease the impact from texture switches, asides from sorting and grouping as much as possible. But for the other vector parameters...

1- Using arrays or structs
Is it faster to send a single array or struct with all vector parameters? Some of the parameters are used on almost every shader, so I can make a struct or array with these "fixed" parameters, + a number of custom ones. Then pass them with a single command.

2- Sharing parameters
In Cg I use cgConnectParameter on common "shared" variables such as the camera position. That means if I update the camera position once, it will be done in all shaders that refer to this shared parameter. Yet I'm not sure if this is the best way to share. But that's probably a question specific on Cg...

3- Not re-sending the parameters if they didn't change
AFAIK, parameters stay with their program. So if I have a single object with 1 shader, I only have to pass the parameters once (until their values change). However, in my case lot's of objects share the same shader-program, but with different parameters.

4.- Storing parameters on the GPU?
Since we can store textures and geometry on the GPU instead of passing them from the CPU, isn't this possible with parameters too? Let's say I have 300 different materials, each with a custom set of parameters. Now upload the bastards to the GPU, and let the shaders look there (they need to know where to look though).

5.- Any other tips on shader parameters?


Cheers
Advertisement
Hodgman's topic on emulating C-Buffers is relevant to your interests:
http://www.gamedev.net/topic/618167-emulating-cbuffers/
Thanks, I'll start reading. And most probably, I will have questions :P T/Cbuffers, is that also available in OpenGL btw?

From my little understanding so far, you just stuff one (or more) big buffers with all the parameters you desire ONCE, then just activate that buffer when going rendering, so you don't have to stop and adjust parameters before rendering another object. So:

// The old way
myShader.activate;
for each object in renderQueue
myShader.parameter(0).set( object.parameter1 );
myShader.parameter(1).set( object.parameter2 );
object.render
--------------------------
<new way>
fill tbuffer with all the parameters we'll need
...

myShader.activate;
tbuffer,activate
for each object in renderQueue
object.render

So far, so good?

From my little understanding so far, you just stuff one (or more) big buffers with all the parameters you desire ONCE, then just activate that buffer when going rendering, so you don't have to stop and adjust parameters before rendering another object. So:
...snip...
So far, so good?


Yeah. Its a restructure so the CPU and GPU both do as little work as they need to. CBuffers don't exist in OpenGL, but i beleive the concept of register-index bound parameters is readily available in either GL3.0 or Cg.
From what I can tell, uniform buffer objects are in some ways similar to cbuffers in D3D. They let you update uniforms in blocks, in the same way as you would to update a vertex buffer, and the block can be shared between shader programs.
Never heard of uniform buffer objects, but that's why they invented Google :) Is a similiar thing also available for textures (directX tbuffer) btw?

Is a similiar thing also available for textures (directX tbuffer) btw?


A texture array, arguably.
http://www.gearboxsoftware.com/
Looks like there's a texture buffer object in OpenGL 3.1+ as well. I don't know what tbuffers are like in Direct3D, but in OpenGL a texture buffer object acts like a texture except you can't specify any texture parameters on them, so it's literally a huge array of data in the form of a texture.
In HLSL a tbuffer is used and declared exactly like a constant buffer. The only difference is on the app side of things, where you create a texture resource and bind that to the device rather than a constant buffer resource. Ultimately it just ends up being a bit of syntatic sugar.

This topic is closed to new replies.

Advertisement