A lot of GPU programs

Started by
9 comments, last by AndyTX 18 years, 5 months ago
In my game engine I use a general vertex and a general fragment program for all shading. This is really slow in some cases where a specialized GPU program would do the job much faster. The problem is that if I write like 10 specialized programs and then want to change something in the general program. I will have to apply the change to all of the 10 specialized programs. This is a real pain! This must be a pretty common problem so I expect there is a solution... like have some precompiler generate all the specialized programs from the general program. Is there a solution? I’m using in Cg but I’m willing to change if some other language is better... // Coorn
Advertisement
One way would be to put all the common functionality in one file and then simply do an #include, just like in c/c++. This will also work with HLSL but I dont think GLSL supports this (might work on NVIDIA cards though because it uses the CG compiler).

HTH
You can write shader fragments, and then use ID3DXFragmentLinker to "merge" them together to build your full shaders. For example, merge lighting and texturing fragments to get a light & tex shader.
Hi there! I´m sorry to ask my question in another one´s thread, but it just fits so nicely and essentially it covers the same material:
a) Are there any simple tutorials for the use of this FragmentLinker, perhaps one just merging a simple light fragment and tex fragment?
b) One thing that has been bothering me for some time now, is the following problem:
Let´s say I have about 10 different shaders I want to use in one frame, I would really love to set the world, view and projection matrix only once for all these shaders. Is there a way that different shaders share the same variables?
Quote:Original post by Anonymous Poster
You can write shader fragments, and then use ID3DXFragmentLinker to "merge" them together to build your full shaders. For example, merge lighting and texturing fragments to get a light & tex shader.


Sorry I'm using OpenGL...

Quote:Original post by nts
One way would be to put all the common functionality in one file and then simply do an #include, just like in c/c++. This will also work with HLSL but I dont think GLSL supports this (might work on NVIDIA cards though because it uses the CG compiler).

HTH


I don't really understand how to use #include to help me with my problem... Could you please explain a bit more?

In your include file you'd have functions to perform all your common functions, e.g. you'd have functions like DoLighting, SkinVertex (for animation in the vertex shader) etc.

Half-Life 2 uses a rather brute force approach of having a tool pregenerate all permutations of a shader from a general shader. Here's an example of how it works:

//STATIC: "OPTION1" 0...1//STATIC: "OPTION2" 0...1static const bool option1 = OPTION1;static const bool option2 = OPTION2;void ShaderMain(InStruct in){    if(option1)    {        //do option1 stuff    }    if(option2)    {        //do option2 stuff    }}


The offline tool looks at the stuff in comments at the top and generates all possible permutations from the ranges you've listed, in this case you'll get a shader with both OPTION1 and OPTION2 #defined to 0, one with OPTION1 #defined to 1 one with OPTION2 #defined to 1 and one with OPTION1 and OPTION2 #defined to 1. Then you have some C++ code that tells the engine what permutation to choose. In this way you can create a general shader that generates many specialised shaders (some of the HL2 shaders have several thousand permutations).

Thank you!
Quote:Original post by matches81
Hi there! I´m sorry to ask my question in another one´s thread, but it just fits so nicely and essentially it covers the same material:
a) Are there any simple tutorials for the use of this FragmentLinker, perhaps one just merging a simple light fragment and tex fragment?
b) One thing that has been bothering me for some time now, is the following problem:
Let´s say I have about 10 different shaders I want to use in one frame, I would really love to set the world, view and projection matrix only once for all these shaders. Is there a way that different shaders share the same variables?


In DirectX, you can tell the compiler to bind a constant to a specific register, and set the constants once

For example:

uniform float4x4 mWorldViewProj : register(c0)

will force the matrix to be bound to register c0. You can then set it with
something like:

device->SetVertexShaderConstantF(0, (float*)&matrix, 4);

One gotcha here is that if you're transforming matrices the usual way:

mul(P,mWorldViewProjection)

the matrices have to be passed in column-major order, so if you're setting shader constants directly, you need to transpose them first.

Quote:Original post by Anonymous Poster
Quote:Original post by matches81
Hi there! I´m sorry to ask my question in another one´s thread, but it just fits so nicely and essentially it covers the same material:
a) Are there any simple tutorials for the use of this FragmentLinker, perhaps one just merging a simple light fragment and tex fragment?
b) One thing that has been bothering me for some time now, is the following problem:
Let´s say I have about 10 different shaders I want to use in one frame, I would really love to set the world, view and projection matrix only once for all these shaders. Is there a way that different shaders share the same variables?


In DirectX, you can tell the compiler to bind a constant to a specific register, and set the constants once

For example:

uniform float4x4 mWorldViewProj : register(c0)

will force the matrix to be bound to register c0. You can then set it with
something like:

device->SetVertexShaderConstantF(0, (float*)&matrix, 4);

One gotcha here is that if you're transforming matrices the usual way:

mul(P,mWorldViewProjection)

the matrices have to be passed in column-major order, so if you're setting shader constants directly, you need to transpose them first.


Or, you can forget about the registers and just declare your variables "shared" i.e. shared uniform float4x4 mWorldViewProj; (just keep the same name for all your hlsl files)
Then, you have to create one ID3DXEffectPool, passing it to D3DXCreateEffect*** everytime you want to load an effet which will then share its parameters with all the other effects using this same pool. Hope this is clear enough.
great! That helped a lot, thx! I will look into this effect pool thingie, as it sounds exactly like the thing I´m looking for. Thx for the hint :)

This topic is closed to new replies.

Advertisement