ShaderGen::synthesize_shader called repeatidly? FPS drops!


I’m experiencing a weird behaviour which materializes in a FPS drop from 50fps down to 1.6fps this
just by adding a shader parameter update in an genericAsyncTask.

In a nutshell: I have a shader attached to a sky box. (similar to EnnOx’s [Nvidia Nature Demo))
Then I set up a dynamic parameter “time” in order to have the clouds moving in the sky.

So, as soon as I add:

AsyncTask::DoneStatus update_clouds(GenericAsyncTask* task, void* data) {
	double vtime = globalClock->get_real_time();
   // render.set_shader_input("time", vtime);   // *** if added this is where the slow down occurs
	return AsyncTask::DS_cont;

The FPS drops drastically.

Digging into the matter, I notice that shaderGenerator.cxx code : CPT(RenderAttrib) ShaderGenerator::synthesize_shader(const RenderState *rs)

is executed exactly 8 times in the first case (ie no time parameter update) then doesn’t seem to be called again,
BUT is basically run at each async call in the second case. (ie if I add render.set_shader_input(“time”, vtime);

This is a fundamental flaw in the auto-shader system: it has to generate a new shader whenever the render state changes in any way. We’re working on a better way to do it in the future, but this is what we have for now.

To avoid this problem in this case, you can save out the text generated by the auto-shader into its own .sha file, and simply load it and apply it directly instead of invoking the auto-shader in the future.


Hi David,

Well to be honest I’m not sure I fully understand what I have to do and how to do it :frowning:

Do you suggest that the original sky.sha source file is being modified by the runtime? In this case where can I find the newly auto-generated shader source code and how can I force it to be read instead of the original one?

BTW. besides sky.sha, I have other shaders that are supposed to be applied to others node in the scene. So I’m sort of puzzled by what actually happens behind the curtains and moreover what I should do :unamused:

I’m not familiar with the autoshader, but as far as I understand (maybe wrongly) your explanation, it seems that autoshader is regenerating a composite shader for the whole scene?

Could you please provide some sketchy hints on how to proceed.



Oh, my apologies. I assumed that you were already using the auto-shader from the nature of the problem. You would be using the auto-shader if you ever called NodePath::set_shader_auto() or ShaderAttrib::set_shader_auto(). In this case, the auto-shader system would synthesize a shader for your nodes according to the render state.

But if you’re using a static shader that you loaded from an .sha file, this doesn’t apply. There’s no reason that the shader should be recompiled each frame. But then there’s no reason that synthesize_shader() should be called at all.

Perhaps you have the auto-shader applied to some nodes other than the ones you intend to influence with the shader input. In this case, you should be careful to apply the shader input change to a node that is not a parent of any of the auto-shader nodes, instead of to render.

Or, perhaps you don’t even need the auto-shader at all, and can use the fixed-function render pipeline on your other nodes.



You hit the point. I had “render.set_shader_auto()” somewhere else in my code.

I can’t recall why I had this statement, I think it may have to do with Shadow casting (can’t remember why)… anyway for the time being I’ll get rid of it

Rgds. Jean-Claude

BTW. Just curious, when an autoshader is issued, where is located the generated (synthesized) .sha file?

It’s not stored on disk.

So, let me guess, in this case one would need to dump the text buffer generated by ShaderGenerator::synthesize_shader
into a file. Correct?

There’s a configuration variable to write it to standard output, I believe it’s called “dump-generated-shaders”.

Thank you rdb,
Will have a look, worth to know!