private void ConvertPixelShaderCaps( RenderSystemCapabilities rsc )
{
var major = 0xFF;
var minor = 0xFF;
SlimDX.Direct3D9.Capabilities minPsCaps = null;
// Find the device with the lowest vertex shader caps.
foreach (var driver in _driverList)
{
var rkCurCaps = driver.D3D9DeviceCaps;
var currMajor = rkCurCaps.PixelShaderVersion.Major;
var currMinor = rkCurCaps.PixelShaderVersion.Minor;
if (currMajor < major)
{
major = currMajor;
minor = currMinor;
minPsCaps = rkCurCaps;
}
else if (currMajor == major && currMinor < minor)
{
minor = currMinor;
minPsCaps = rkCurCaps;
}
}
var ps2A = false;
var ps2B = false;
var ps2X = false;
// Special case detection for ps_2_x/a/b support
if (major >= 2)
{
if ((minPsCaps.PS20Caps.Caps & PixelShaderCaps.NoTextureInstructionLimit) != 0 &&
(minPsCaps.PS20Caps.TempCount >= 32))
{
ps2B = true;
}
if ((minPsCaps.PS20Caps.Caps & PixelShaderCaps.NoTextureInstructionLimit) != 0 &&
(minPsCaps.PS20Caps.Caps & PixelShaderCaps.NoDependentReadLimit) != 0 &&
(minPsCaps.PS20Caps.Caps & PixelShaderCaps.ArbitrarySwizzle) != 0 &&
(minPsCaps.PS20Caps.Caps & PixelShaderCaps.GradientInstructions) != 0 &&
(minPsCaps.PS20Caps.Caps & PixelShaderCaps.Predication) != 0 &&
(minPsCaps.PS20Caps.TempCount >= 22))
{
ps2A = true;
}
// Does this enough?
if (ps2A || ps2B)
{
ps2X = true;
}
}
switch (major)
{
case 1:
// no boolean params allowed
rsc.FragmentProgramConstantBoolCount = 0;
// no integer params allowed
rsc.FragmentProgramConstantIntCount = 0;
// float params, always 4D
// NB in ps_1_x these are actually stored as fixed point values,
// but they are entered as floats
rsc.FragmentProgramConstantFloatCount = 8;
break;
case 2:
// 16 boolean params allowed
rsc.FragmentProgramConstantBoolCount = 16;
// 16 integer params allowed, 4D
rsc.FragmentProgramConstantIntCount = 16;
// float params, always 4D
rsc.FragmentProgramConstantFloatCount = 32;
break;
case 3:
// 16 boolean params allowed
rsc.FragmentProgramConstantBoolCount = 16;
// 16 integer params allowed, 4D
rsc.FragmentProgramConstantIntCount = 16;
// float params, always 4D
rsc.FragmentProgramConstantFloatCount = 224;
break;
}
// populate syntax codes in program manager (no breaks in this one so it falls through)
switch (major)
{
case 3:
if ( minor > 0 )
rsc.AddShaderProfile( "ps_3_x" );
rsc.AddShaderProfile( "ps_3_0" );
goto case 2;
case 2:
if ( ps2X )
rsc.AddShaderProfile( "ps_2_x" );
if ( ps2A )
rsc.AddShaderProfile( "ps_2_a" );
if ( ps2B )
rsc.AddShaderProfile( "ps_2_b" );
rsc.AddShaderProfile( "ps_2_0" );
goto case 1;
case 1:
if ( major > 1 || minor >= 4 )
rsc.AddShaderProfile( "ps_1_4" );
if ( major > 1 || minor >= 3 )
rsc.AddShaderProfile( "ps_1_3" );
if ( major > 1 || minor >= 2 )
rsc.AddShaderProfile( "ps_1_2" );
rsc.AddShaderProfile( "ps_1_1" );
rsc.SetCapability( Graphics.Capabilities.FragmentPrograms );
break;
}
}