[require] % The ternary operator works differently in sm6. See sm6-ternary.shader_test. shader model < 6.0 [pixel shader todo(sm<4)] uniform float4 x; float4 main() : sv_target { return x.x ? x : x - 1; } [test] uniform 0 float4 2.0 3.0 4.0 5.0 todo(sm<4 | glsl) draw quad probe all rgba (2.0, 3.0, 4.0, 5.0) uniform 0 float4 0.0 10.0 11.0 12.0 todo(sm<4 | glsl) draw quad probe all rgba (-1.0, 9.0, 10.0, 11.0) [pixel shader todo(sm<4)] uniform float4 x; float4 main() : sv_target { float4 ret; ret.x = x.x ? x.x : 1; ret.y = x.y ? 2 : x.y; ret.z = ret.w = 0.0; return ret; } [test] uniform 0 float4 1.1 3.0 4.0 5.0 todo(sm<4 | glsl) draw quad probe all rgba (1.1, 2.0, 0.0, 0.0) [pixel shader todo(sm<4)] float4 f; float4 main() : sv_target { float f1 = 0.1, f2 = 0.2, f3; f3 = f.x ? (f1 = 0.5) + 0.2 : (f2 = 0.6); return float4(f1, f2, f3, 0.0); } [test] uniform 0 float4 1.0 0.0 0.0 0.0 todo(sm<4 | glsl) draw quad probe all rgba (0.5, 0.6, 0.7, 0.0) [pixel shader] float4 x, y, z; float4 main() : sv_target { return x ? y : z; } [test] uniform 0 float4 0.0 1.0 0.0 -3.0 uniform 4 float4 1.0 2.0 3.0 4.0 uniform 8 float4 5.0 6.0 7.0 8.0 todo(sm<4 | glsl) draw quad probe all rgba (5.0, 2.0, 7.0, 4.0) % The usual type conversion is applied to the first and second expression, as % long as they are numeric. [pixel shader fail] uniform float2x4 a; uniform float3x2 b; float4 main() : sv_target { 0 ? a : b; return 0; } [pixel shader] static float3x3 a = {0, 1, 2, 3, 4, 5, 6, 7, 8}; static float2x2 b = {.1, .2, .3, .4}; float4 main() : sv_target { return float4(1 ? a : b); } [test] todo(glsl) draw quad probe all rgba (0.0, 1.0, 3.0, 4.0) [pixel shader] static float3 a = {0, 1, 2}; static float4 b = {5, 6, 7, 8}; float4 main() : sv_target { return float4(0 ? a : b, 1.0); } [test] todo(glsl) draw quad probe all rgba (5.0, 6.0, 7.0, 1.0) % More restrictions are placed on the type of the first (condition) operand, % relative to the common type computed from the other two (result). Either: % * the class and dimensions must match exactly; % * the condition operand is scalar; % * the result operands are scalar; % * one is a typeN and the other is a type1xN [pixel shader fail] uniform float4 cond; uniform float2x2 a, b; float4 main() : sv_target { return float4(cond ? a : b); } [pixel shader fail] uniform float2x2 cond; uniform float4 a, b; float4 main() : sv_target { return float4(cond ? a : b); } [pixel shader] static float2x2 cond = {1, 0, 0, 1}; static float2x2 a = {1, 2, 3, 4}; static float2x2 b = {5, 6, 7, 8}; float4 main() : sv_target { return float4(cond ? a : b); } [test] todo(glsl) draw quad probe all rgba (1.0, 6.0, 7.0, 4.0) [pixel shader fail] uniform float3 cond; uniform float4 a, b; float4 main() : sv_target { (cond ? a : b); return 0; } [pixel shader fail] uniform float4 cond; uniform float4x1 a, b; float4 main() : sv_target { (cond ? a : b); return 0; } % As may be expected, this yields the type of the arguments, not the conditional. [pixel shader] static float4 cond = {1, 0, 0, 1}; static float1x4 a = {1, 2, 3, 4}; static float1x4 b = {5, 6, 7, 8}; float4 main() : sv_target { return (cond ? a : b)[0]; } [test] todo(glsl) draw quad probe all rgba (1.0, 6.0, 7.0, 4.0) [pixel shader todo] static float1x4 cond = {1, 0, 0, 1}; static float4 a = {1, 2, 3, 4}; static float4 b = {5, 6, 7, 8}; float4 main() : sv_target { return (cond ? a : b)[0]; } [test] todo draw quad probe all rgba (1.0, 1.0, 1.0, 1.0) [pixel shader fail] uniform float1x4 cond; uniform float4 a, b; float4 main() : sv_target { return (cond ? a : b)[0][0]; } [pixel shader] static float1 cond = {0}; static float1x1 a = {2}; static float1x1 b = {3}; float4 main() : sv_target { return (cond ? a : b)[0][0]; } [test] todo(glsl) draw quad probe all rgba (3.0, 3.0, 3.0, 3.0) [pixel shader todo(sm<4)] uniform float cond; uniform float4 a, b; float4 main() : sv_target { return float4(cond ? a : b); } [test] uniform 0 float4 1.0 0.0 0.0 0.0 uniform 4 float4 1.0 2.0 3.0 4.0 uniform 8 float4 5.0 6.0 7.0 8.0 todo(sm<4 | glsl) draw quad probe all rgba (1.0, 2.0, 3.0, 4.0) [pixel shader] // "scalar" can mean any 1-component numeric type. static float1x1 cond = {0}; static float4 a = {1, 2, 3, 4}; static float4 b = {5, 6, 7, 8}; float4 main() : sv_target { return float4(cond ? a : b); } [test] todo(glsl) draw quad probe all rgba (5.0, 6.0, 7.0, 8.0) [pixel shader] uniform float4 cond; uniform float4 a, b; float4 main() : sv_target { return float4(cond ? a.x : b.x); } [test] uniform 0 float4 1.0 0.0 1.0 0.0 uniform 4 float4 1.0 2.0 3.0 4.0 uniform 8 float4 5.0 6.0 7.0 8.0 todo(sm<4 | glsl) draw quad probe all rgba (1.0, 5.0, 1.0, 5.0) [pixel shader] // "scalar" can mean any 1-component numeric type. static float4 cond = {1, 0, 0, 1}; static float1x1 a = {2}; static float1x1 b = {3}; float4 main() : sv_target { return float4(cond ? a : b); } [test] todo(glsl) draw quad probe all rgba (2.0, 3.0, 3.0, 2.0) % Objects can be used, but their types have to be identical. [pixel shader todo] Texture2D t; float4 main() : sv_target { Texture2D tmp = 0 ? t : t; return 0; } [pixel shader fail todo] Texture2D t; float4 f; float4 main() : sv_target { f ? t : t; return 0; } [pixel shader fail] Texture2D t; Texture3D u; float4 main() : sv_target { 0 ? t : u; return 0; } % Of course objects cannot be used as the condition. [pixel shader fail] Texture2D t; float4 main() : sv_target { t ? 0 : 1; return 0; }