Sign in to follow this  
Ashkan

Generating Shader Permutations - keeping the balance

Recommended Posts

Ashkan    451
I'm currently in the process of generating shader permutations using preprocessor directives but found myself in trouble while trying to balance the load between vertex and pixel shaders. Based on some recent discussions, some other samples I checked and some time spent playing around with the idea, I found it rather easy to set up the shaders for scenarios in which all or most of the lighting calculations is done exclusively in vertex or pixel shaders. The general idea is to feed the non-varying parameters such as light properties via uniform parameters and iterate over it in vertex or pixel shader to calculate its contribution. What has bugged me though is the process of distributing the workload. Here is a sample to clear my point:
//------------------------------------
// Uniform Parameters
//------------------------------------

// some uniform parameters such as light properties (type, color, falloff and such)


//------------------------------------
// Varying Parameters
//------------------------------------
struct vertexInput_textured {
    float3 position                     : POSITION;
    float3 normal                       : NORMAL;
    float2 texcoord                     : TEXCOORD0;
};

struct vertexOutput {
    float4 position                     : POSITION;
    float3 normal                       : TEXCOORD0;
    float2 texcoord                     : TEXCOORD1;
    float3 lightDirection               : TEXCOORD2;
    float3 viewDirection                : TEXCOORD3;
};

vertexOutput VS_TransformDiffuse( vertexInput_textured IN ) {
    // calculate the lightDirection and viewDirection in the vertex-shader
}

float4 PS_DiffuseSpecular( vertexOutput IN  ) : COLOR0 {
    // do the calculations in the pixel shaders
}



If we were to calculate lightDirection in the pixel shader (or had done all the calculations in the vertex shader on the other hand) things were just hunk dory. The problem here is that lightDirection is passed to the fragment shader inside vertexOutput structure so every other light adds a member to this vertexOutput structure, so I need a way to procedurally generate all these vertexOuput structures and their corresponding pixel shaders or else I would end up manually writing them in the effect file; something which was to be avoided in the first place. Add texcoords (for multi-texturing purposes) to this mix and it would become a living hell. I think I'm missing something here since FarCry or HL2 (that I think used this approach) had a lot of per-pixel effects. Should all the calculations be done either on vertex or pixel shader? Isn't there any way of balancing the load? Any ideas? Thanks

Share this post


Link to post
Share on other sites
deathkrush    350
How about this:


struct vertexOutput {
float4 position : POSITION;
float3 normal : TEXCOORD0;
float2 texcoord : TEXCOORD1;
float3 viewDirection : TEXCOORD2;

#if LIGHTS >= 0
float3 light0Direction : TEXCOORD3;
#endif

#if LIGHTS >= 1
float3 light1Direction : TEXCOORD4;
#endif

#if LIGHTS >= 2
float3 light2Direction : TEXCOORD5;
#endif

};

Share this post


Link to post
Share on other sites
Ashkan    451
Thanks deathkrush. That was interesting, but HOLY COW I just came up with a better solution more pleasant to our instincts: arrays! I just realized that one can actually use arrays in those structures (big discovery, huh?) [grin]. The size of this array can be set using a #define. Here's a revised version:


struct vertexOutput {
float4 position : POSITION;
float3 normal : TEXCOORD0;
float2 texcoord : TEXCOORD1;
float3 viewDirection : TEXCOORD2;
float3 lightDirection[MAX_LIGHT] : TEXCOORD3;
};


Share this post


Link to post
Share on other sites
wolf    852
Those vertex structures are much too big and any NVIDIA card (probably also ATI cards) will get a hiccup with those. Performance of the vertex shader is dependend on the number of attributes you feed it. With a vertex structure like this your vertex shader performance is pretty much dead.

Share this post


Link to post
Share on other sites
Ashkan    451
Quote:
Performance of the vertex shader is dependend on the number of attributes you feed it.

If you're concerned about the bus traffic caused by fat streams sent to the video card or the vertex processor been brought down to it's knees, I think you've probably mistaken that structure for a structure representing the incoming vertex's layout. That structure is actually what's get passed down to the fragment shader. Anyway, I'm still very open to suggestions. Have you got any better ideas?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this