Precompiled effect files and macros

Started by
7 comments, last by 21st Century Moose 11 years, 6 months ago
Hello,
I'll try to explain my problem and I will be grateful for any feedback.


To change some graphics settings that affect shaders (especially texture filtering mode and max anisotropy) I use macros passed to D3DXCreateEffectFromFile. The .fx files use that macros with preprocessor #if directives, so everything happens during effect compilation.

But, D3DXCreateEffectFromFile takes quite a long time to compile .fx files (it can be even around 0.2 seconds for a SINGLE effect file) so I thought I could use precompiled .fxo files (created for example with the tool fxc.exe) which would probably load much faster. But if I'm not mistaken, I wouldn't be able to set macros in the D3DXCreateEffectFromFile anymore, I would have to set them in the command line when running fxc.exe...

So the question is, what other solutions would you suggest to allow me to change for example texture filtering or max anisotropy - that means values directly written in the sampler definition in an effect file?
Advertisement
Typically you compile the shader using fxc.exe using every possible combination of options that you might require at runtime, and end up with a large collection of compiled shaders.

N.B. ignoring D3DX "effects" for a moment, texture filtering modes and max anisotropy are sampler states, not shader code, so they can be set programmatically -- though yes, D3DX FX syntax does allow you to specify default values for those states in your shader code.
However, I'm not very familiar with D3DX FX structures (I use regular D3D shaders), so I can't tell you how to override it.
Yea, I was also thinking about putting samplers out of the effect file, assigning them to a specific register and just refering to that register in the shaders.

There are however some else values I'm currently setting via the macros, like shadow map size. But those can be just constants set from the C++ code.
It's been a very long time, but I think you can assign a sampler state a value from a global int declared in your .fx file. Then at runtime you can set the int value with ID3DXEffect::SetInt. Otherwise you could always just call SetSamplerState yourself.
I'd personally just call SetSamplerState myself, and leave the default sampler states in the Effect file unset (i.e. just declare it as "sampler mySampler;").

What I have done before is to do what MJP suggests and assign a state from a shader constant. The Effect code looks something like this:
int myMipFilter;

sampler s = sampler_state
{
mipfilter = <myMipFilter>;
};


Then in your C++ you do:effect->SetInt ("myMipfilter", D3DTEXF_LINEAR);

(That's largely working from memory so please don't copy/paste this.)

A third way is to attach an ID3DXEffectStateManager to your Effect and set the states you want from there. See http://msdn.microsoft.com/en-us/library/windows/desktop/bb205795%28v=vs.85%29.aspx for more info on this. This is probably the approach I'd prefer as you can also add some state filtering to your Effect with it.

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

Thank you guys. I'll decide which way to go, I think I prefer to move sampler settings away from the effect file and just use SetSamplerState, but I'll see how it will turn out when I'll be putting it into my code.


A third way is to attach an ID3DXEffectStateManager to your Effect and set the states you want from there. See http://msdn.microsof...5(v=vs.85).aspx for more info on this. This is probably the approach I'd prefer as you can also add some state filtering to your Effect with it.

I already am using ID3DXEffectStateManager to filter redundant changes. It's been quite a long time so I'll have to look at it again and see how it could be used.

Thank you guys. I'll decide which way to go, I think I prefer to move sampler settings away from the effect file and just use SetSamplerState, but I'll see how it will turn out when I'll be putting it into my code.


I should have added that if you do this it will go much easier on you if you specify explicit sampler registers in your HLSL code, like so:sampler mySampler : register(s0)

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.


I should have added that if you do this it will go much easier on you if you specify explicit sampler registers in your HLSL code, like so:sampler mySampler : register(s0)

Hm, the question is whether it is much easier (as you say) or rather the only way how to do it? How else would I know which number to use as the first parameter of SetSamplerState?

Btw, that's what I'm already doing with my shadow map texture, because I haven't found any way how to "unset" a texture using the effect framework and I was getting debug runtimes warnings about using a texture that has been previously assigned as a render target. When I have the shadow map texture in a fixed register, I can easily set it to NULL using SetTexture.

[quote name='mhagain' timestamp='1349479725' post='4987281']
I should have added that if you do this it will go much easier on you if you specify explicit sampler registers in your HLSL code, like so:sampler mySampler : register(s0)

Hm, the question is whether it is much easier (as you say) or rather the only way how to do it? How else would I know which number to use as the first parameter of SetSamplerState?
[/quote]

An effect state manager would also let you do it, but otherwise - yeah - it is kinda necessary isn't it?

Direct3D has need of instancing, but we do not. We have plenty of glVertexAttrib calls.

This topic is closed to new replies.

Advertisement