diff --git a/Makefile.am b/Makefile.am index b6b8da71..0d5f9f13 100644 --- a/Makefile.am +++ b/Makefile.am @@ -197,6 +197,7 @@ vkd3d_shader_tests = \ tests/hlsl/object-field-offsets.shader_test \ tests/hlsl/object-parameters.shader_test \ tests/hlsl/object-references.shader_test \ + tests/hlsl/patch-syntax.shader_test \ tests/hlsl/point-sprite.shader_test \ tests/hlsl/pointer-cast.shader_test \ tests/hlsl/pow.shader_test \ diff --git a/tests/hlsl/patch-syntax.shader_test b/tests/hlsl/patch-syntax.shader_test new file mode 100644 index 00000000..b48e5e38 --- /dev/null +++ b/tests/hlsl/patch-syntax.shader_test @@ -0,0 +1,564 @@ +% Patch objects are equivalent to const arrays if not used as inputs/outputs to tessellation shaders. + +[pixel shader] +InputPatch patch; + +float4 main() : SV_TARGET +{ + return patch[0]; +} + +[test] +uniform 0 float 1 +uniform 1 float 2 +draw quad +probe (0, 0) rgba(1.0, 1.0, 1.0, 1.0) + +[pixel shader] +OutputPatch patch; + +float4 main() : SV_TARGET +{ + return patch[0]; +} + +[test] +uniform 0 float 1 +uniform 1 float 2 +draw quad +probe (0, 0) rgba(1.0, 1.0, 1.0, 1.0) + +% Assigning a patch with an array is not allowed in SM6. +[pixel shader fail(sm>=6)] +float data[2]; + +float4 main() : SV_TARGET +{ + InputPatch patch = data; + return patch[0]; +} + +[test] +uniform 0 float 1 +uniform 1 float 2 +draw quad +probe (0, 0) rgba(1.0, 1.0, 1.0, 1.0) + +[pixel shader fail] +float data[2]; + +float4 main() : SV_TARGET +{ + InputPatch patch = data; + patch[0] = 3; + return patch[0]; +} + +[pixel shader fail(sm<6)] +float4 main() : SV_TARGET +{ + InputPatch patch; // Missing initializer. + return 0; +} + +[pixel shader fail(sm<6)] +InputPatch patch; // Element count must be non-zero. + +float4 main() : SV_TARGET +{ + return 0; +} + +[pixel shader fail(sm>=6)] +float data[2]; + +float4 main() : SV_TARGET +{ + OutputPatch patch = data; + return patch[0]; +} + +[test] +uniform 0 float 1 +uniform 1 float 2 +draw quad +probe (0, 0) rgba(1.0, 1.0, 1.0, 1.0) + +[pixel shader fail] +float data[2]; + +float4 main() : SV_TARGET +{ + OutputPatch patch = data; + patch[0] = 3; + return patch[0]; +} + +[pixel shader fail(sm<6)] +float4 main() : SV_TARGET +{ + OutputPatch patch; // Missing initializer. + return 0; +} + +[pixel shader fail(sm<6)] +OutputPatch patch; // Element count must be non-zero. + +float4 main() : SV_TARGET +{ + return 0; +} + +% InputPatch parameters can only be used in hull and geometry shaders (SM>=5). + +[pixel shader fail] +struct data +{ + float4 val : VAL; +}; + +float4 main(InputPatch patch) : SV_TARGET +{ + return 0; +} + +[hull shader todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant() +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +[hull shader todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(InputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +[domain shader fail(sm<6)] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + + [domain("isoline")] +float4 main(patch_constant_data input, InputPatch patch) : POSITION +{ + return 0; +} + +[geometry shader fail(sm<5) todo(sm>=5)] +struct data +{ + float4 val : VAL; +}; + + [maxvertexcount(1)] +void main(InputPatch patch, inout PointStream vout) +{ + vout.Append(patch[0]); +} + +% OutputPatch parameters can only be used in hull shader patch constant functions and domain shaders. + +[pixel shader fail] +struct data +{ + float val : VAL; +}; + +float4 main(OutputPatch patch) : SV_TARGET +{ + return 0; +} + +[hull shader fail] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant() +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(OutputPatch patch) : POSITION +{ + return patch[0].val; +} + +[hull shader todo] +struct data +{ + float4 val : VAL; +}; + +struct out_data +{ + float outval : OUTVAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(OutputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +out_data main() +{ + return (out_data)0; +} + +[domain shader todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + + [domain("isoline")] +float4 main(patch_constant_data input, OutputPatch patch) : POSITION +{ + return 0; +} + +[geometry shader fail] +struct data +{ + float4 val : VAL; +}; + + [maxvertexcount(1)] +void main(OutputPatch patch, inout PointStream vout) +{ + vout.Append(patch[0]); +} + +% Patch parameters can't have more than 32 control points. + +[hull shader todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant() +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +[hull shader fail] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant() +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +[domain shader todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + + [domain("isoline")] +float4 main(patch_constant_data input, OutputPatch patch) : POSITION +{ + return 0; +} + +[domain shader fail] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + + [domain("isoline")] +float4 main(patch_constant_data input, OutputPatch patch) : POSITION +{ + return 0; +} + +% However, patch objects used in non tessellation shaders can have more than 32 elements. +[pixel shader] +InputPatch patch; + +float4 main() : SV_TARGET +{ + return patch[0]; +} + +% Multiple patch parameters are not allowed. + +[hull shader fail] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant() +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch, uint i : SV_OutputControlPointID, InputPatch patch2) : POSITION +{ + return 0; +} + +[domain shader fail] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + + [domain("isoline")] +float4 main(OutputPatch patch, patch_constant_data input, OutputPatch patch2) : POSITION +{ + return 0; +} + +% InputPatch types must match between the main function and the patch constant function of a hull shader. + +[hull shader fail todo] +struct data +{ + float4 val : VAL; +}; + +struct data2 +{ + float4 apple : APPLE; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(InputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +[hull shader fail todo] +struct data +{ + float4 val : VAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(InputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +float4 main(InputPatch patch) : POSITION +{ + return 0; +} + +% The type of a OutputPatch parameters in a hull shader patch constant function must match +% the output type of the shader's main function. + +[hull shader fail] +struct data +{ + float4 val : VAL; +}; + +struct out_data +{ + float outval : OUTVAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(OutputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +out_data main() +{ + return (out_data)0; +} + +[hull shader fail] +struct out_data +{ + float outval : OUTVAL; +}; + +struct patch_constant_data +{ + float edges[2] : SV_TessFactor; +}; + +patch_constant_data patch_constant(OutputPatch patch) +{ + return (patch_constant_data)0; +} + + [domain("isoline")] + [outputcontrolpoints(2)] + [partitioning("integer")] + [outputtopology("point")] + [patchconstantfunc("patch_constant")] +out_data main() +{ + return (out_data)0; +}