Here are my findings on uniforms and DirectX 9.
1. Native int and bitwise operators are supported only from SM4.0
Source:
https://en.wikipedia.org/wiki/High-level_shader_language and MJP from gamedev (much more solid).
In SM2.0 there are the Constant Integer Registers i#, but they are used only by loop - ps and rep - ps.
Source:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb219858%28v=vs.85%29.aspx2. In SM2 and 3 you can use common modulo operator % with ints but it not very fast and it is better to do it with floats.
Source:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb509631(v=vs.85).aspx3. Float, int and bool uniforms are all stored in the Constant Float Registers c#. Each of these registers consists in 4 floats (x,y,z,w).
Source: some tests with Microsoft PIX on a Nvidia card and AMD ShaderAnalyzer.
4. As said, bools are also stored in c# and not in the b# registers.
b# are the Constant Boolean Registers, they exist also in SM2.0, they are "a collection of bits used in static flow control
instructions (for example, if bool - ps - else - ps - endif - ps). They can be set using defb - ps or SetPixelShaderConstantB."
Source:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb219856%28v=vs.85%29.aspxNow I see a problem: does 'SetPixelShaderConstantB' declare these bools as 'defb' does ? If so, then I don't have
to declare them in my shader, but if I use these bools and don't declare them, how can I can compile the shader?
So I think that these b# can be used only in HLSL assembly (maybe).
Also, you cannot specify a registry b# for an uniform bool like this:
uniform bool cMyBool : registry(b0);because here the b# are the Constant buffer registers, they are different things from the Constant Boolean Registers.
Source:
http://msdn.microsoft.com/en-us/library/windows/desktop/dd607359%28v=vs.85%29.aspxAnyway, this isn't a problem since an uniform bool is stored in a c# register.
5. In Urho to set a bool shader parameter we use "void Graphics::SetShaderParameter(StringHash param, bool value)".
Here it uses SetPixelShaderConstantB which works only on b#, so to make the bools work we could use SetPixelShaderConstantF to write
on c#, something like this:
void Graphics::SetShaderParameter(StringHash param, bool value)
{
SetShaderParameter(param, (float)value);
}This works (c# = (value > 0.0) ? 1.0 : 0.0), but...
6. Sometimes when there is an uniform bool in the shader code, the compiler (D3DCompile) nukes all the uniforms (even the ones in
Uniforms.hlsl and I think also some code). To be sure this doesn't happen I found two ways (but I could not understand why):
- specify a registry c# for the bool, for example:
uniform bool cMyBool : registry(c0);
void PS(...)
{
...
if (cMyBool)
...
}- specify the attribute 'flatten' on the 'if':
uniform bool cMyBool;
void PS(...)
{
...
[flatten] if (cMyBool)
...
}7. Similary, int uniforms can be set with 'SetPixelShaderConstantF', you cannot use 'SetPixelShaderConstantI' because it is for i# registers only.
8. I've also noticed that the ID3DXEffectPool interface (the one you get with D3DXCreateEffectFromFile) works with no problems with:
effect->SetFloat(), effect->SetInt(), effect->SetBool(), so I think that maybe inside it uses 'SetPixelShaderConstantF'.
Conclusions:
- Adding support for int and IntVector2 shader uniforms can be done on OpenGL and DirectX9 (with a little modify on the material XML), but it
adds nothing to DirectX9 (and they are slow), better to use floats; on OpenGl it can be useful for prototyping (and they should be fast).
- To make uniform bools work on DirectX9 the Set___ShaderConstantB could be replaced with Set___ShaderConstantF, this works but it seems
an hack, and their use can create problems difficult to pinpoint (point 6).
These notes are not much trustworthy, there is no experience behind only a few tests done last week.
I think it is better for Urho to leave it as it is now: few gains to face problems not fully understood.