From: Francisco Casas fcasas@codeweavers.com
--- Makefile.am | 1 + tests/hlsl/fx-syntax.shader_test | 578 +++++++++++++++++++++++++++++++ 2 files changed, 579 insertions(+) create mode 100644 tests/hlsl/fx-syntax.shader_test
diff --git a/Makefile.am b/Makefile.am index a9ea14338..0d3ca17a3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -106,6 +106,7 @@ vkd3d_shader_tests = \ tests/hlsl/function-return.shader_test \ tests/hlsl/function.shader_test \ tests/hlsl/fwidth.shader_test \ + tests/hlsl/fx-syntax.shader_test \ tests/hlsl/gather-offset.shader_test \ tests/hlsl/gather.shader_test \ tests/hlsl/getdimensions.shader_test \ diff --git a/tests/hlsl/fx-syntax.shader_test b/tests/hlsl/fx-syntax.shader_test new file mode 100644 index 000000000..9e8a78aa6 --- /dev/null +++ b/tests/hlsl/fx-syntax.shader_test @@ -0,0 +1,578 @@ +% For now, these tests are just to check proper parsing of effects syntax. +% Most of these tests are useless as effects. + + +% Arbitrary names are allowed in the lhs of state block entries. +[pixel shader] +sampler sam +{ + Foobar = 3; +}; + +float4 main() : sv_target { return 0; } + + +% Undefined identifiers are allowed in state blocks. +[pixel shader] +sampler sam +{ + Filter = ANISOTROPIC; +}; + +float4 main() : sv_target { return 0; } + + +% Multiple state blocks for array variables are a thing. +[pixel shader todo] +sampler sams[2] +{ + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + } +}; + +float4 main() : sv_target { return 0; } + + +[pixel shader fail(sm<6)] +sampler sams[2] +{ + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + }, // trailing comma not allowed. +}; + +float4 main() : sv_target { return 0; } + + +% Multiple state blocks for multi-dimensional array variables are a thing. +[pixel shader todo] +sampler sams[2][2] +{ + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + } +}; + +float4 main() : sv_target { return 0; } + + +% State blocks cannot be nested further than one level, regardless of multi-dimensionality. +[pixel shader fail(sm<6)] +sampler sams[2][2] +{ + { + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + } + }, + { + { + Filter = ANISOTROPIC; + }, + { + Filter = ANISOTROPIC; + } + } +}; + +float4 main() : sv_target { return 0; } + + +% Arrays of size 1 can still use a single state block without the need to put it inside a list. +[pixel shader] +sampler sams[1] +{ + Filter = ANISOTROPIC; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks may have bracket initializers on the rhs. +[pixel shader todo] +sampler sam +{ + MaxAnisotropy = 3; + cat = {1, 2, {3, "string"}}; + dogs[3] = {1, {2, {4}}, 3, any_identifier}; +}; + +float4 main() : sv_target { return 0; } + + +% Even though using undefined identifiers is allowed, calls to undefined functions are not. +[pixel shader fail(sm<6)] +sampler sam +{ + cat = fun(); +}; + +float4 main() : sv_target { return 0; } + + +% PixelShader and VertexShader are valid identifiers for the lhs +[pixel shader todo] +sampler sam +{ + pixelShader = 20; + PixelShader = 25; + VertexShader = 30; + vertexshader = 35; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for numeric types. +[pixel shader todo] +float f +{ + MaxAnisotropy = 3; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for texture types. +[pixel shader] +Texture2D tex +{ + MaxAnisotropy = 3; +}; + +float4 main() : sv_target { return 0; } + + +% Same rules apply for technique passes +[pixel shader todo] +technique +{ + pass + { + cat = {1, 2, {3, "string"}}; + dogs[3] = {1, {2, {4}}, 3, any_identifier}; + } +} + +float4 main() : sv_target { return 0; } + + +% Multi-dimensional arrays on the lhs on state blocks are syntax errors. +[pixel shader fail(sm<6)] +sampler sam +{ + dogs[1][1] = 1; +}; + +float4 main() : sv_target { return 0; } + +[pixel shader fail(sm<6)] +technique +{ + pass + { + dogs[1][1] = 1; + } +} + +float4 main() : sv_target { return 0; } + + +% Test special "compile" keyword syntax to compile pixel and vertex shaders +[pixel shader todo] +float4 fun() : sv_target +{ + return 0; +} + +sampler sam +{ + cat = compile ps_2_0 fun(); +}; + +float4 main() : sv_target { return 0; } + + +[pixel shader todo] +float4 fun() : sv_target +{ + return 0; +} + +technique +{ + pass + { + cat = compile ps_2_0 fun(); + } +} + +float4 main() : sv_target { return 0; } + + +% Only uniform arguments are expected, even if undefined identifiers are used. +[pixel shader todo] +float4 fun(uniform float4 a, float4 b, uniform float4 c) : sv_target +{ + return a + b + c; +} + +technique +{ + pass + { + cat = compile ps_2_0 fun(foobar, foobar); // Notice 2 arguments, not 3 + } +} + +float4 main() : sv_target { return 0; } + + +[pixel shader fail(sm<6)] +float4 fun(uniform float4 a, float4 b, uniform float4 c) : sv_target +{ + return a + b + c; +} + +technique +{ + pass + { + // passing 3 arguments here is not valid because the function has only 2 uniforms. + cat = compile ps_2_0 fun(1, 2, 3); + } +} + +float4 main() : sv_target { return 0; } + + +% Test effect groups syntax +[pixel shader todo fail(sm>=6)] +fxgroup group1 +{ + technique10 + { + pass + { + TurboEncabulator = prefabulated + aluminite; + malleable = logarithmic - casing; + } + pass pass1 + { + spurving_bearings = pentametric_fan; + hydrocoptic = marzlevanes; + } + } + technique11 tech1 + { + pass + { + Lunar = Waneshaft; + } + } +} + +float4 main() : sv_target { return 0; } + + +% Effect groups cannot have a "technique" without version +[pixel shader fail] +fxgroup group1 +{ + technique + { + } +} + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for DepthStencilState +[pixel shader todo] +DepthStencilState dss1 +{ + DepthEnable = false; + DepthWriteMask = Zero; + DepthFunc = Less; + random_field = 12; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for BlendState. +[pixel shader todo] +BlendState bs1 +{ + random_field = 1; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for VertexShader and PixelShader +[pixel shader] +PixelShader ps1 +{ + random_field = 1; +}; + +VertexShader vs1 +{ + random_field = 1; +}; + +float4 main() : sv_target { return 0; } + + +% State blocks are valid for RasterizerState +[pixel shader todo] +RasterizerState rs +{ + random_field = 1; +}; + +float4 main() : sv_target { return 0; } + + +% Undefined identifiers cannot be indexed. +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +DepthStencilState dss1 +{ + RandomField = foobar[2]; +}; + + +% Undefined identifiers can be swizzled with .x which proves that they are considered scalar +[pixel shader todo] +float4 main() : sv_target { return 0; } + +DepthStencilState dss1 +{ + RandomField = foobar.x; +}; + +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +DepthStencilState dss1 +{ + RandomField = foobar.y; +}; + + +% The type of previously defined variables is respected, but array indexes are not checked. +[pixel shader todo] +float4 arr[3]; + +float4 main() : sv_target { return 0; } + +DepthStencilState dss1 +{ + RandomField = arr[90]; +}; + + +% The type of previously defined variables is respected, and swizzles are checked. +[pixel shader fail(sm<6)] +float3 vec; + +float4 main() : sv_target { return 0; } + +DepthStencilState dss1 +{ + RandomField = vec.w; +}; + + +% Test function call syntax for state blocks. Unlike assignment syntax, only these names are allowed. +% The parameter count is also checked. +[pixel shader todo] +sampler sam +{ + SetBlendState(foo, bar, baz); // 3 parameters + SetDepthStencilState(foo, 2); // 2 parameters + SetRasterizerState(foo); // 1 parameter + SetVertexShader(vs); // 1 parameter + SetDomainShader(ds); // 1 paramter + SetHullShader(100); // 1 parameter + SetGeometryShader(foo + bar); // 1 parameter + SetPixelShader(ps1); // 1 parameter + SetComputeShader("random string"); // 1 parameter + OMSetRenderTargets(RTV0, RTV1, RTV2, RTV3, RTV4, RTV5, RTV6, RTV7, DSV); // 2 to 9 parameters +}; + +float4 main() : sv_target { return 0; } + + +[pixel shader fail(sm<6)] +sampler sam +{ + SetSomeotherState(); +}; + +float4 main() : sv_target { return 0; } + + +% Test the same thing on technique passes +[pixel shader todo] +technique tech1 +{ + pass pass1 + { + SetBlendState(foo, bar, baz); + SetDepthStencilState(foo, 2); + SetRasterizerState(foo); + SetVertexShader(vs); + } +} + +float4 main() : sv_target { return 0; } + + +% It is not allowed to call the functions to set state blocks on the rhs using the assignment syntax +% for state groups or passes. +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +technique +{ + pass + { + cat = SetPixelShader(foobar); + } +} + + +% Test use of a DepthStencilState in SetDepthStencilState(). +[pixel shader todo] +DepthStencilState dss1 +{ + DepthEnable = false; + DepthWriteMask = Zero; + DepthFunc = Less; + foobar_Field = 22; +}; + +float4 main() : sv_target { return 0; } + +technique tech1 +{ + pass pass1 + { + SetDepthStencilState(NULL, dss1); + } +} + + +% It not allowed to call the functions to set states outside state blocks or passes. +[pixel shader fail] +DepthStencilState dss1 +{ + DepthEnable = false; + DepthWriteMask = Zero; + DepthFunc = Less; +}; + +float4 main() : sv_target +{ + SetDepthStencilState(NULL, dss1); + return 0; +} + + +% Test the CompileShader() syntax. +[pixel shader todo fail(sm>=6)] +float arg1, arg2; + +float4 main_vertex(uniform float a) : sv_position { return a; } + +float4 main(uniform float a) : sv_target { return a; } + // ^ dxc expects a semantic here. + +PixelShader ps1 = CompileShader(ps_2_0, main(arg2)); +VertexShader vs1 = CompileShader(vs_2_0, main_vertex(arg1)); + +technique10 tech1 +{ + pass pass1 + { + SetVertexShader(vs1); + SetPixelShader(ps1); + } +} + + +% Undefined identifiers are not allowed if CompileShader() is used outside a state block. +[pixel shader fail] +float4 main(uniform float a) : sv_target { return a; } + +PixelShader ps1 = CompileShader(ps_2_0, main(foobar)); + + +% But undefined identifiers are allowed if inside a state block. +[pixel shader todo fail(sm>=6)] +float4 main_vertex(uniform float a) : sv_position { return a; } + +float4 main(uniform float a) : sv_target { return a; } + // ^ dxc expects a semantic here. + +technique tech1 +{ + pass pass1 + { + SetVertexShader(CompileShader(vs_2_0, main_vertex(foo))); + SetPixelShader(CompileShader(ps_2_0, main(bar))); + } +} + + +% Again only uniform parameters are expected +[pixel shader fail] +float aa, bb; + +float4 main(uniform float a, float b) : sv_target { return a; } + +PixelShader ps1 = CompileShader(ps_2_0, main(aa, bb)); + + +% Only a set of target profiles are allowed +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +PixelShader ps1 = CompileShader(ps_6_0, main()); + +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +PixelShader ps1 = CompileShader(fs_2_0, main()); + + +% Shaders cannot be passed around to another variable: "Initializer must be literal expressions.". +[pixel shader fail(sm<6)] +float4 main() : sv_target { return 0; } + +PixelShader ps1 = CompileShader(ps_2_0, main()); +PixelShader ps2 = ps1; +