[pixel shader fail] float4 func(); float4 main() : sv_target { return func(); } % It's legal to call an undefined function in unused code, though. [pixel shader] float4 func(); float4 unused() { return func(); } float4 main() : sv_target { return 0; } [pixel shader fail] void func(inout float o) { o += 0.1; } float4 main() : sv_target { float x = 0; func(x + 1); return 0; } [pixel shader fail] void func(inout float2 o) { o += 0.1; } float4 main() : sv_target { float2 x = 0; func(x.yy); return 0; } [pixel shader fail] void func(out float o) { o = 0.1; } float4 main() : sv_target { const float x = 0; func(x); return x; } [pixel shader fail] void func(inout float o) { } float4 main() : sv_target { const float x = 0; func(x); return x; } [pixel shader fail] void func() { } float4 main() : sv_target { return func(); } [pixel shader fail(sm<6)] void foo() { } void bar() { return foo(); } float4 main() : sv_target { bar(); return 0; } % The function must have been at least declared before calling it. It may have % been declared with a different but compatible type, though. [pixel shader fail] float4 main() : sv_target { func(); return 0; } void func() { } [pixel shader] void func(); float4 main() : sv_target { func(); return 0; } void func() { } [pixel shader fail] void func(float arg); float4 main() : sv_target { func(); return 0; } void func() { } [pixel shader] /* This is something of an internal test: we need to make sure that we use the * correct variables for a function's arguments and returns regardless of * whether it's been defined yet. * * Also, make sure that we can handle the case where the argument names differ. */ float2 concat(float x, float y); float2 func(void) { return concat(0.1, 0.2); } float2 concat(float a, float b) { return float2(a, b); } float4 main() : sv_target { return float4(func(), concat(0.3, 0.4)); } [test] draw quad probe (0, 0) rgba (0.1, 0.2, 0.3, 0.4) [pixel shader] float func(in float a, out float b, inout float c) { c -= 0.2; b = a * 2; return a + 0.2; } float4 main() : sv_target { float x[2], ret; x[0] = 0.1; x[1] = 0.9; ret = func(0.3, x[0], x[1]); return float4(ret, x[0], x[1], 0); } [test] draw quad probe (0, 0) rgba (0.5, 0.6, 0.7, 0) [pixel shader] void func(in float a, inout float2 b) { b.y += 0.1; b *= a; } float4 main() : sv_target { float3 q = float3(0.1, 0.2, 0.3); func(3.0, q.zx); func(0.5, q.yz); return float4(q, 0); } [test] draw quad probe (0, 0) rgba (0.6, 0.1, 0.5, 0) % Recursion is forbidden. [pixel shader notimpl(sm<6) fail(sm>=6)] void bar(); void foo() { bar(); } void bar() { foo(); } float4 main() : sv_target { foo(); return 0; } [pixel shader notimpl(sm<6) fail(sm>=6)] % Even trivially finite recursion is forbidden. void func(bool x) { if (x) func(false); } float4 main() : sv_target { func(true); return 0; } [pixel shader] float func(float a) { return a + 1; } float4 main() : sv_target { return float4(func(1.0), func(2.0), func(5.0), func(6.0)); } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 6.0, 7.0) [pixel shader] float func(float a) { return a + 1; } float4 main() : sv_target { float4 a = {func(1.0), func(2.0), func(5.0), func(6.0)}; return a; } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 6.0, 7.0) % Inline modifier [pixel shader] inline float func(float a) { return a + 1; } float4 main() : sv_target { float4 a = {func(1.0), func(2.0), func(5.0), func(6.0)}; return a; } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 6.0, 7.0) % Inline modifier used on entry point [pixel shader fail(sm>=6)] float func(float a) { return a + 1; } inline float4 main() : sv_target { float4 a = {func(1.0), func(2.0), func(5.0), func(6.0)}; return a; } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 6.0, 7.0) % Export modifier [pixel shader] export float4 main() : sv_target { return float4(1.0, 2.0, 3.0, 4.0); } [test] draw quad probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0) % Default parameter values [pixel shader] float func(float a, float b = 2.0f, float c = 3.0f, float d=4.0f) { return a + b + c + d; } float4 main() : sv_target { return float4(func(1.0), func(1.0, 3.0), func(1.0, 3.0, 5.0), func(1.0, 3.0, 5.0, 7.0)); } [test] draw quad probe (0, 0) rgba (10.0, 11.0, 13.0, 16.0) [pixel shader] float4 func(float4 a = 1.0, float4 b = float4(1.0, 2.0, 3.0, 4.0)) { return a + b; } float4 main() : sv_target { return func() + func(float4(-3.0, -4.0, -5.0, -6.0), float4(3.0, 4.0, 5.0, 6.0)); } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 4.0, 5.0) [pixel shader fail(sm>=6)] float4 func(float4 a = 1.0, float4 b = {1.0, 2.0, 3.0, 4.0}) { return a + b; } float4 main() : sv_target { return func() + func(float4(-3.0, -4.0, -5.0, -6.0), float4(3.0, 4.0, 5.0, 6.0)); } [test] draw quad probe (0, 0) rgba (2.0, 3.0, 4.0, 5.0) % For parameters, the order of matrix initializers is row-major. [pixel shader] float4 func(float2x2 m = float2x2(1, 2, 3, 4)) { return float4(m); } float4 main() : sv_target { return func(); } [test] draw quad probe (0, 0) rgba (1.0, 2.0, 3.0, 4.0) % Missing default value for parameter c. [pixel shader fail] float func(float a, float b = 1.0f, float c) { return a + b + c; } float4 main() : sv_target { return 0; } % Output parameters can't have default values for SM < 6. % The default values for output parameters are ignored for SM6. [pixel shader fail(sm<6)] float func(float a, out float b = 1.0) { b += a; return b; } float4 main() : sv_target { return 0; } [pixel shader fail(sm<6)] float func(float a, out float b = 1.0) { b += a; return b; } float4 main() : sv_target { float x = 2.0; float y = func(4.0, x); return float4(x, y, 0, 0); } [test] todo(sm>=6 | glsl) draw quad probe (0, 0) rgba (4.0, 4.0, 0.0, 0.0) [pixel shader fail(sm<6)] float func(float a, inout float b = 1.0) { b += a; return b; } float4 main() : sv_target { float x = 2.0; float y = func(4.0, x); return float4(x, y, 0, 0); } [test] todo(glsl) draw quad probe (0, 0) rgba (6.0, 6.0, 0.0, 0.0) % Parameters before outputs can't have default values. [pixel shader fail] float func(float a = 1.0f, out float b) { return a; } float4 main() : sv_target { return 0; } [pixel shader fail] float func(float a = 1.0f, inout float b) { return a; } float4 main() : sv_target { return 0; }