Jump to content

  • Log In with Google      Sign In   
  • Create Account


shader system implementation


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
45 replies to this topic

#1 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 15 September 2005 - 02:15 AM

Hi I have read some threads about how to implement a decent shader system especially this one they suggest a method using dlls to keep the system flexible they export a base class and implement it in the dll I wonder how I could handle several shader dlls with implicit linking(without loadlibrary("xxx.dll") From what I understand this isn t possible that way since it would always choose the dll it finds first so you probably don t get the right one one solution I could think of, actually more a hack than a solution ENGINE: export baseclass SHADERMANAGER_DLL: import baseclass export derived class #n getprocedure( return instance of derived class #n) SHADER#n_DLL: import derived class #n implement derived class # n this way the SHADERMANAGER_DLL would be implicitly linked and would implicitly link to the SHADER#n_DLL the getprocedure would return a instance of a shader implemented in a dll any idea if that works? a more straight forward solution would be explicit linking which allows you to choose which dll to load at runtime what way would you suggest/propose? i would like to allow modders to implement custom shaders

Sponsor:

#2 rick_appleton   Members   -  Reputation: 857

Like
0Likes
Like

Posted 15 September 2005 - 02:22 AM

Part of the appeal of the mentioned system comes from being able to 'patch' the game with additonal shaders after release, by simply creating a new dll. This implies you need to check at startup what dlls there are and dynamically load them (with LoadLibrary on windows).

#3 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 15 September 2005 - 08:34 PM

Ok that seems to be the easiest and straight forward way to handle this problem


How would you process with the implementation?
give each shader class a information struction describing its capabilities
and put the render code into the shader class?


so the mapper specifies which shader implementation to use
so the engine loads a map and finds a shader that request implementation "sm3.0" for example

now the shader manager searches for the dll that implements the sm3.0 shader


then
- sort all geometry to render by shader
- get a instance of the shader implementation
- render(geometry){shaderinstance->setstates(); shaderinstance->draw(geometry);shaderinstance->unsetstates()};

proceed until everything is rendered


or would you suggest a different approach?

#4 rick_appleton   Members   -  Reputation: 857

Like
0Likes
Like

Posted 15 September 2005 - 09:05 PM

It's probably similar to what you described yes. Although I think most people who have implemented this stuff have added an extra level of indirection. The mapper does not specify which shader he wants exactly, but the resulting effect he wants to create.

At engine startup the renderer parses all the shaders and sorts them according to the effect they implement, and the quality of it. All shaders that aren't supported by the hardware can be unloaded again.

Then at rendertime, find the effect, find the associated shader (this would normally be the best one, but according to quality settings, it might be a lower quality implementation of the effect), and then call that as you described.

You'll also want to take a good look at this thread.

#5 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 16 September 2005 - 10:16 AM

Maybe packing shaders into DLL-s isn't very good idea.
Why should you do that, for example?
It gives freedom to the point, one can build very custom vertex declarations, and prebuild vb/ib-s, but... this is not exactly responsibility of a shader...
Shader shades geometry, whatever it is.
Packing, or even creating geometry maybe is not quite it responsibility. It is responsibility of some renderer subsystem.
Imagine this - you released a game, and want to enhance it with grass... You build a grass-shader and release its DLL... but where to put that grass? Well...
Ok, you have the grass, but it is lame, and you want to make it cool. You write a shader, and release it... Is it pracital? I'd say - no...
This is just an argument, against a system described in threads mentioned - do not waste your precious time, implementing such monsters, especially when there is no need to.

Implement:
1. Shader compiler system (based on preprocessor), that can get a shader source, and create a family of shaders from it. For example, try to encode more parameters into single shader source, like light variation, fog variation, quality variation, etc.
2. System of managing shader parameters, and uploading shader constants to the shaders. (Setting parameters each frame vs binding pointers to shader constants)
3. Effect system, that describe a group of shaders, for each situation in which an object must be rendered - for different light scenarios, fog scenarios, shadowmap, quality, renderpath, etc...
4. A really advanced system would be, some way to let your artist control/create shaders. System can vary from relatively simple shader parametric system, where for each shader written we have some set of parameters (fog: linear, height, linear+height), (lighting: diffuse+ambient, lerp( diffuse, ambient ), diffuse-only, ...), etc. Artist can just choose options from combo-boxes, then we set proper defines to the compiler and produce a shader.
More advanced system would be composing shader from primitives/blocks, like UE3 shader editor/Offset software shader editor for example.

My 2c.

#6 Guimo   Members   -  Reputation: 463

Like
0Likes
Like

Posted 16 September 2005 - 10:29 AM

Hi,
Its not a wise idea to implement effects as DLLs. Effect is just another type of resource. Doing this is like trying to load textures as DLLs.

If using DX, try the D3DXFramework. It can compile the effects at runtime and if you create a effect manager, then you can load and unload your effects at will and setup them with some simple params.

Luck!
Guimo

#7 mikeman   Members   -  Reputation: 2195

Like
0Likes
Like

Posted 16 September 2005 - 09:20 PM

I think what you're looking for is an effect, not shader, system. Basically, something that will define:

1)How many rendering passes will there be
2)The initial states(matrices,lights,textures,blending modes...) for each pass
3)The shaders that the pass will use

IMO, if you're after easy modding, it's very risky to require modders to compile a dll that will be linked with the main .exe. They have to be very careful to get it right. Different compilers or settings(aligment,padding,etc...) may result to big problems.

I think the best solution by far is to use some sort of scripting. Then the game will be modded by just editing a text file. If you're using D3D, then the D3DXFramework is just fine. Otherwise, you can use Lua or SmallTalk or something like that(even boost::spirit?), or even implement a scripting system yourself. It doesn't have to be anything fancy, the most complex thing you need to do is set the states. You can probably pull it off with some sscanf() commands.

#8 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 16 September 2005 - 11:14 PM

I think you missunderstood the concept behind this implementation

the shader dll doesn t implement the effects you want to implement it implements the functionality you offer for shaders

e.g.:
a grass shader with (normal grass, boring grass, animated grass)
lets say you work with an older graphics card and implement these shaders mentioned above
they all provide some properties used to render them
now you switched to a modern graphic card and you want to update the graphics quality you just release a new dll with a higher priority to provide the functionality used by the shaders, just in a modern manner maybe with enhanced features
the shader dll itself runs a test on you system to check if everything is available otherwise the system chooses the old dll

this allows you to specialize a generalized representation of a effect for certain graphic cards without rewriting and updating a ton of code

the shader dll itself just does the state processing
the effect properties are still seperated in a effects/shader file


and i don t use D3D and i would like to stay independent from APIs so the effects framework of D3D is no option in my eyes

#9 python_regious   Members   -  Reputation: 929

Like
0Likes
Like

Posted 17 September 2005 - 12:59 AM

Quote:
Original post by mikeman
I think what you're looking for is an effect, not shader, system. Basically, something that will define:

1)How many rendering passes will there be
2)The initial states(matrices,lights,textures,blending modes...) for each pass
3)The shaders that the pass will use

IMO, if you're after easy modding, it's very risky to require modders to compile a dll that will be linked with the main .exe. They have to be very careful to get it right. Different compilers or settings(aligment,padding,etc...) may result to big problems.

I think the best solution by far is to use some sort of scripting. Then the game will be modded by just editing a text file. If you're using D3D, then the D3DXFramework is just fine. Otherwise, you can use Lua or SmallTalk or something like that(even boost::spirit?), or even implement a scripting system yourself. It doesn't have to be anything fancy, the most complex thing you need to do is set the states. You can probably pull it off with some sscanf() commands.


I disagree with your definition of an effect. Personally, to me an effect has absolutely nothing to do with how the effect is implemented (so, render passes and so on). All the effect does is provide resources to implement the effect - so for instance, it says "You have these streams and uniforms available to create this effect", some form of shader (I'm not talking about GLSL or co) would then implement the effect however it likes.

I personally went with the scripting approach, whereby I have an effect file - which says what effects there are (with a little description of what that effect should do), and what resources are available to implement that effect. I then have a series of shader files that have a number of profiles ( to support different types of hardware ), with different compliances with how well it supports the said effect. Each profile can then implement the effect in as many passes or using whatever tech it needs. At load time the effects are resolved to a profile in a shader based on what the hardware supports such that the profile with the highest supported compliance is used. Multiple shaders can support the same effect - but the one with the highest compliance will always be used, so patching using a new shader is easy.

There are disadvantages to using a script based system - one big one being you can't really do arbitary processing.
If at first you don't succeed, redefine success.

#10 Yann L   Moderators   -  Reputation: 1794

Like
0Likes
Like

Posted 17 September 2005 - 02:00 AM

Although the DLL shader approach works really well in practice, and is very robust and extensible, I was always thinking of ways to get rid of it someday. It's complex, platform dependent (you need to distribute your shaders specifically compiled for each platform), and doesn't really allow for rapid prototyping and visual shader development as easily as I would like to.

Unfortunately, no alternative (especially primitive script or shader program based ones, like the DX effect framework) offer the extreme flexibility and scalability of the DLL based effect-shader system. So, currently we're still using it extensively. Our current system uses over 60 shader DLLs, with more than 300 shaders. And still, it is lightning fast.

But the future lies in a different approach: JIT compiled shader meta languages. Right now, the resources needed to render a specific effect through a shader are almost always explicitely defined. This has to change: the shader compiler should extract, optimize, and request all needed resources on his own. Things like the number of passes shouldn't even appear in the code anymore: a render pass, a shader program or an attribute are just resources, much like a CPU register or opcode. An appropriate compiler must automatically recognize and optimize the use of such resources, and request them from the render manager on demand.

Approaches like the Sh meta language go into the right direction, but are still not flexible enough.


#11 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 17 September 2005 - 02:06 AM

Quote:
Original post by Basiror
e.g.:
a grass shader with (normal grass, boring grass, animated grass)
lets say you work with an older graphics card and implement these shaders mentioned above
they all provide some properties used to render them
now you switched to a modern graphic card and you want to update the graphics quality you just release a new dll with a higher priority to provide the functionality used by the shaders, just in a modern manner maybe with enhanced features
the shader dll itself runs a test on you system to check if everything is available otherwise the system chooses the old dll

this allows you to specialize a generalized representation of a effect for certain graphic cards without rewriting and updating a ton of code

the shader dll itself just does the state processing
the effect properties are still seperated in a effects/shader file


People all over the world update their graphics, by releasing patches, which include executable and the art needed.
Making DLL system just for the ease of updaing the graphics is little pointless, because the typical executable size is nothing to download today, and provides a lot more freedom to implement visual features for modern cards (if we are talking about that) - no shader can ADD new features, nor modify quantities of older ones (say adding light shafts, fog layers, spider-webs over the walls, etc.).
IF you go that way, the executable patching is the way, DLL-patching is half-the-way, not-really-there.

A system with priorities looks dangerous. Tweaking parameters by hand, and overriding priorities looks dangerous.
We create shader, set a priority and hope it will be resolved.
Better is to explicitly put the new shader, in the effects we want with the priority we want - it is more stable.

#12 LarsMiddendorf   Members   -  Reputation: 122

Like
0Likes
Like

Posted 17 September 2005 - 02:19 AM

@Yann L:
How do you solve the problem with the big number of shader permutations?
With PS30 HW you can put 4 or more lights(with shadowmaps) into one rendering pass. But each light/fog should also have its own shader fragment: point light, spot lights, lights with a cubemap, volumetric fog. Combined with some material shaders the number of combinations grows exponentially.
Precompiling is impossible but creating on the fly is also slow. Cg's interfaces are nice, but they don't really help here, because the cause a recompilation. Generating asm shaders is doable, but you lose specific compiler optimizations(and it's even impossible with glsl).




#13 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 17 September 2005 - 02:36 AM

Quote:
Original post by LarsMiddendorf


One working system that I know of, just compiles all combinations in preprocess, search unique resulting shaders and removes all duplicates.



#14 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 17 September 2005 - 03:00 AM

Well as mentioned above i don t want to encapsulate the shader itself into the dll
i would rather implement a set of features in the dll which makes use of latest extensions available
and in a shader file you define the effects you d like to achive with a description language

at loadtime the system checks which shaders to load,
checks the dlls for supported features and availability on the current hardware(e.g.: multi texturing with 2 4 8 16 layers *just an example don t rant me*)
and links the shaders with the dlls

the dlls just provide some extended functionality you offer the artists which on the other side could not be implemented with a scripting language

of course i could recompile a executeable and upload it, but no modder can customize the rendering pipeline to fit his needs and i certainly don t want to release my engine source only the gameplay components which are encapsulated into a seperate dll as you know it from halflife1

light shafts, spider webs or what ever aren t features that are implemented by a shader, light shafts belong to your sky model implementation in my opinion

effects aren t shader related either,

for me a shader defines
- material properties, effect name on bullet hit
- texture names ....
- blending operations
- parallax mapping dot3 bumpmapping and such

effects:
- name of effect
- particle effects
- sound effects
- other effect types

to implement the functionality of the shader as i defined it in the context of my engine, the dll provides a interface for the capabilities your hardware offers

you can imagine it as a renderer plugin with the little addition that everyone can customize it specialize it for certain hardware ....


as for the supply of information to render you could implement another system that allows the creation of additional render information such as a color array for each vertex in a mesh
all you had to do is to implement a api into your mesh class, or whatever you use to represent your geometry, that allows a preprocess to be run that generates the additional data so you shader can handle it

you could implement a preprocess inside your shader that runs the preprocess on the mesh

this is just an idea to extent the whole think without touching the executeable's code
of course you can t implement each gimmick you wish to that way but i allows for a lot of customization without much of an effort


[Edited by - Basiror on September 17, 2005 9:00:25 AM]

#15 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 17 September 2005 - 03:29 AM

Quote:
Original post by Basiror
of course i could recompile a executeable and upload it, but no modder can customize the rendering pipeline to fit his needs and i certainly don t want to release my engine source only the gameplay components which are encapsulated into a seperate dll as you know it from halflife1


The patching by releasing entire executable was to show that releasing a DLL will not enhance top-level graphics in a way that releasing whole executable will.

About modding - do you really want your possible modders can alter shader database?
It can be done, without messing with executable code completely, just keeping shaders as source (or ability to load them that way too), and possibly cache compiled results later.
Or (even better), release the tools that let your artists create shaders! :)

#16 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 17 September 2005 - 03:47 AM

you still mix the shader and the dlls

the shaders are just a description of the surface and maybe vertex and pixel shader programs,

the dll however implements a high more abstracted part to provide additional functionality just as if you d link the SDL library to your c++ program and make use of SDL's build in functions to setup a window

thats a huge difference in my eyes

#17 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 17 September 2005 - 03:52 AM

Quote:
Original post by Basiror
you still mix the shader and the dlls

the shaders are just a description of the surface and maybe vertex and pixel shader programs,

the dll however implements a high more abstracted part to provide additional functionality just as if you d link the SDL library to your c++ program and make use of SDL's build in functions to setup a window

thats a huge difference in my eyes


Yes, we use different terminology. Give an example, of one DLL and shader usage, like you see them to be used.

#18 Yann L   Moderators   -  Reputation: 1794

Like
0Likes
Like

Posted 17 September 2005 - 04:09 AM

Quote:
Original post by Zemedelec
People all over the world update their graphics, by releasing patches, which include executable and the art needed.
Making DLL system just for the ease of updaing the graphics is little pointless, because the typical executable size is nothing to download today, and provides a lot more freedom to implement visual features for modern cards (if we are talking about that) - no shader can ADD new features, nor modify quantities of older ones (say adding light shafts, fog layers, spider-webs over the walls, etc.).

Of course the DLL approach can do that - that's the whole point of it. And obviously it is not always possible to patch the executable for simple reasons such as application deployment (games are not the only sector where shaders are used), extensibility without access to the application or game source code (what would Max or Maya be without plugins), etc. The whole idea behind the DLL approach is flexibility. Patching the executable completely takes away that flexibility.

Quote:
Original post by Zemedelec
IF you go that way, the executable patching is the way, DLL-patching is half-the-way, not-really-there.

Executable patching is often not an option, and to be frank, it is a pretty primitive way of extending functionality of your software. See Plugins.

Quote:
Original post by Zemedelec
A system with priorities looks dangerous. Tweaking parameters by hand, and overriding priorities looks dangerous.
We create shader, set a priority and hope it will be resolved.
Better is to explicitly put the new shader, in the effects we want with the priority we want - it is more stable.

I think you didn't quite understand the system. There are absolutely no stability concerns, the system is stable in itself. In fact, it is much more stable and reliable in selecting an appropriate shader than a manual approach could ever be. Especially on large scale system, with many shaders.

Quote:

How do you solve the problem with the big number of shader permutations?

They're generated and compiled on the fly right now. One must be careful about terminology here: many people use "shader" as an equivalent of a "shader program". That is incorrect. A shader is a structure, visual description and algorithm to simulate a certain visual appearance. Part of a shader can be a shader program (eg. a GLSL shader), but this is not mandatory.

Taking this into account, shaders will never suffer permutation problems. Shader programs will - and those can be auto-generated by their corresponding parent shader. On the fly compiling isn't ultra fast, but this was never a real issue in my experience. Takes at most a couple of seconds, when the effect system resolves the shaders.

#19 Basiror   Members   -  Reputation: 241

Like
0Likes
Like

Posted 17 September 2005 - 04:36 AM

Quote:
Original post by Zemedelec
Yes, we use different terminology. Give an example, of one DLL and shader usage, like you see them to be used.



shader <shadername>
{
stream(vertex,normal,color,blendfactors);
.....
}




now lets say you simply render your scnene with pure vertex arrays and basic opengl lighting so the shader above fullfits your needs

however the auther wants to use dot3 bumpmapping so he has to tell the render what he needs


shader <shadername>
{
stream(vertex,normal,color,blendfactors);
enable dot3_bumpmap.
normalmap "some.tga"
.....
}



the DLL features dot3_bumpmap and normalmap and knows what to do with those keywords
in this case the dll and the shader are linked *hence: implicitly*
however another approach would be to specifiy the dll's name within the shader to make guaranteed use of a certain dll

so in your mesh you have to run a preprocess or you run the initialization the first time you render a mesh although this might lead to lag spikes

the TBN needs to be calculated ....

this is just an example on how i would use it in addition you could store seperate streams created by the preprocess of the dll
the whole concept of interaction of geometry with the additional functionality still needs to be outlined in a straight forward and clear way but thats the basic principle i thought of




#20 Zemedelec   Members   -  Reputation: 229

Like
0Likes
Like

Posted 17 September 2005 - 04:55 AM

Quote:
Original post by Yann LOf course the DLL approach can do that - that's the whole point of it. And obviously it is not always possible to patch the executable for simple reasons such as application deployment (games are not the only sector where shaders are used), extensibility without access to the application or game source code (what would Max or Maya be without plugins), etc. The whole idea behind the DLL approach is flexibility. Patching the executable completely takes away that flexibility.


I was talking about the shader-into-DLL approach, not general DLL concept.
No doubt, updating a part of a system, rather than whole system is more flexible, if implemented.

As for DLL updating as is, a rant:
Software, that do that and have plugin structure have serious requirements to do so - it is developed often by large teams, that create/update parts independantly. And for other concerns, like stability.
Nothing of that concerns the typical game scenario, games imho are not so big software.

Quote:
Original post by Yann LExecutable patching is often not an option, and to be frank, it is a pretty primitive way of extending functionality of your software. See Plugins.

If we target system complexity, that could be good point to start... :)
My personal decidion would be not to trade the design/implement time for pluggable system that can update everything, for the sake of uploading 1.5M more. I would go for stable-old (KISS) solution... but its just me, yes.

Quote:
Original post by Yann LI think you didn't quite understand the system. There are absolutely no stability concerns, the system is stable in itself. In fact, it is much more stable and reliable in selecting an appropriate shader than a manual approach could ever be. Especially on large scale system, with many shaders.

I agree with one - this system will ALWAYS produce an output for asked shader. Be it solid color, at the end.
The thing I don't like about it, is that problem: I want to manually control the fallback of given shader on lower systems for effect A, and for effect B differently and explicitly. Keep good specular on one of them, but remove AO for one, and opposite for the other.
What I understand from the system you described in the oh-so-long thread, was that it will break the description of the shader into a set of smaller compiled and running on that hardware shaders, with the highest priority.
Can't see how this is more predictable and easy-to-develop for a typical not-shader intensive game. For me, it's like having quite many renderpaths, and being unable to guarantee the visual quality in one of them. Maybe it is suitable for software, but for games - can't agree.

And for the sake of "graphic theory" nature of the forum, I totally agree with the post about shader abstraction beyond the passes and profiles.




Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS