diff --git a/Makefile.am b/Makefile.am index 3787389b..0db71d67 100644 --- a/Makefile.am +++ b/Makefile.am @@ -69,6 +69,7 @@ vkd3d_shader_tests = \ tests/conditional.shader_test \ tests/floor.shader_test \ tests/hlsl-array-dimension.shader_test \ + tests/hlsl-attributes.shader_test \ tests/hlsl-bool-cast.shader_test \ tests/hlsl-clamp.shader_test \ tests/hlsl-comma.shader_test \ @@ -104,6 +105,7 @@ vkd3d_shader_tests = \ tests/hlsl-normalize.shader_test \ tests/hlsl-numeric-constructor-truncation.shader_test \ tests/hlsl-numeric-types.shader_test \ + tests/hlsl-numthreads.shader_test \ tests/hlsl-return-implicit-conversion.shader_test \ tests/hlsl-return-void.shader_test \ tests/hlsl-shape.shader_test \ diff --git a/tests/hlsl-attributes.shader_test b/tests/hlsl-attributes.shader_test new file mode 100644 index 00000000..db011873 --- /dev/null +++ b/tests/hlsl-attributes.shader_test @@ -0,0 +1,120 @@ +% Test HLSL attribute syntax. The compiler ignores unrecognized attributes, so +% we need to get the parsing syntax right. Most of the following tests which +% succeed print warnings. + +[pixel shader todo] + + [numthreads] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [ numthreads ] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [numthreads(1)] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [numthreads("")] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [numthreads("one")] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + +uniform float4 f; + + [numthreads(1, "one", 3 + 9, -9.8e4, -float2(1, 2), f)] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [numthreads()] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [numthreads(1,)] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [numthreads(f)] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + /* Test an invalid constructor. */ + [numthreads(float2(1))] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [not_a_real_attribute_name] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + +uniform float4 f; + + [f] +float4 main() : sv_target { return 0; } + +[pixel shader fail] +% This is valid IDL syntax, but not HLSL. + [one, two] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [one][two] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [one][one] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [one][one(1)] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [one][One] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + + [numthreads] +float4 main(); + + [numthreads] +float4 main() : sv_target { return 0; } + +[pixel shader todo] + +/* Expressions with side effects are forbidden in attributes—see + * hlsl-numthreads.shader_test for an example—but not if the attribute is + * ignored. */ +static int i = 1; + + [one(i++)] + [two(++i)] + [three(i = 4)] +float4 main() : sv_target { return 0; } + +[pixel shader fail] + + [one] +float4 f; + +float4 main() : sv_target { return 0; } diff --git a/tests/hlsl-numthreads.shader_test b/tests/hlsl-numthreads.shader_test new file mode 100644 index 00000000..f0ef5f62 --- /dev/null +++ b/tests/hlsl-numthreads.shader_test @@ -0,0 +1,192 @@ +% Test allowed syntax for the "numthreads" attribute. + +[require] +shader model >= 5.0 + +[compute shader todo] + + [numthreads(1, 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads] +void main() {} + +[compute shader fail] + + [numthreads(1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(1, 1, 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(0, 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(1, 0, 1)] +void main() {} + +[compute shader fail] + + [numthreads(1, 1, 0)] +void main() {} + +[compute shader fail] + + [numthreads(-1, 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(1, -1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(1, 1, -1)] +void main() {} + +[compute shader fail] + + [numthreads(1, -1, -1)] +void main() {} + +[compute shader todo] + + [numthreads(uint(1), 1, 1)] +void main() {} + +[compute shader todo] + + [numthreads(int(1), 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(float(1), 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads(uint1(1), 1, 1)] +void main() {} + +[compute shader todo] + + [numthreads(int(1), 1, 1)] +void main() {} + +[compute shader todo] + + [numthreads(1 + 1, 1, 1)] +void main() {} + +[compute shader fail] + + [numthreads("1", 1, 1)] +void main() {} + +[compute shader todo] +static int x = 1; + + [numthreads(x, 1, 1)] +void main() {} + +[compute shader fail todo] + +void main() {} + +[compute shader fail] + + [NumThreads(1, 1, 1)] +void main() {} + +[compute shader todo] + + [numthreads(1, 1, 1)] +void main(); + +void main() {} + +[compute shader fail] + +void main() {} + + [numthreads(1, 1, 1)] +void main(); + +[compute shader fail] + +void main(); + + [numthreads(1, 1, 1)] +void main() {} + +[compute shader fail] + +/* Expressions with side effects are forbidden in attributes (but not if the + * attribute is ignored). */ + +static int x = 1; + + [numthreads(x++, 1, 1)] +void main() {} + +[compute shader fail] + +static int x = 1; + + [numthreads(++x, 1, 1)] +void main() {} + +[compute shader fail] + +static int x = 1; + + [numthreads((x = 2), 1, 1)] +void main() {} + +[compute shader todo] + +static int x = 1; + + [numthreads(++x, 1, 1)] +void func() {} + + [bogus(++x)] + [numthreads(1, 1, 1)] +void main() { func(); } + +[uav 0] +format r32 float +size (2, 2) + +1.0 1.0 +1.0 1.0 + +[compute shader todo] +/* Attributes are taken from the first function, and dropped from the second. */ +RWTexture2D u; + + [numthreads(2, 1, 1)] +void main(uint2 id); + + [numthreads(1, 2, 1)] +void main(uint2 id : sv_dispatchthreadid) +{ + u[id] = 2.0; +} + +[test] +todo dispatch 1 1 1 +probe uav 0 (0, 0) r (2.0) +probe uav 0 (0, 1) r (1.0) +probe uav 0 (1, 0) r (2.0) +probe uav 0 (1, 1) r (1.0) diff --git a/tests/shader_runner.c b/tests/shader_runner.c index fb4ece26..4750b946 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -82,6 +82,8 @@ enum parse_state STATE_SAMPLER, STATE_SHADER_COMPUTE, STATE_SHADER_COMPUTE_TODO, + STATE_SHADER_INVALID_COMPUTE, + STATE_SHADER_INVALID_COMPUTE_TODO, STATE_SHADER_INVALID_PIXEL, STATE_SHADER_INVALID_PIXEL_TODO, STATE_SHADER_PIXEL, @@ -792,6 +794,13 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const shader_source_size = 0; break; + case STATE_SHADER_INVALID_COMPUTE: + case STATE_SHADER_INVALID_COMPUTE_TODO: + todo_if (state == STATE_SHADER_INVALID_COMPUTE_TODO) + compile_shader(runner, shader_source, shader_source_len, "cs", true); + shader_source_len = 0; + break; + case STATE_SHADER_INVALID_PIXEL: case STATE_SHADER_INVALID_PIXEL_TODO: todo_if (state == STATE_SHADER_INVALID_PIXEL_TODO) @@ -868,6 +877,14 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const { state = STATE_SHADER_COMPUTE_TODO; } + else if (!strcmp(line, "[compute shader fail]\n")) + { + state = STATE_SHADER_INVALID_COMPUTE; + } + else if (!strcmp(line, "[compute shader fail todo]\n")) + { + state = STATE_SHADER_INVALID_COMPUTE_TODO; + } else if (!strcmp(line, "[require]\n")) { state = STATE_REQUIRE; @@ -995,6 +1012,8 @@ void run_shader_tests(struct shader_runner *runner, int argc, char **argv, const case STATE_PREPROC_INVALID: case STATE_SHADER_COMPUTE: case STATE_SHADER_COMPUTE_TODO: + case STATE_SHADER_INVALID_COMPUTE: + case STATE_SHADER_INVALID_COMPUTE_TODO: case STATE_SHADER_INVALID_PIXEL: case STATE_SHADER_INVALID_PIXEL_TODO: case STATE_SHADER_PIXEL: