diff --git a/Makefile.am b/Makefile.am index 988c31c4..d838007b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -206,6 +206,7 @@ vkd3d_shader_tests = \ tests/hlsl/return-implicit-conversion.shader_test \ tests/hlsl/return.shader_test \ tests/hlsl/round.shader_test \ + tests/hlsl/rt-format-mismatch.shader_test \ tests/hlsl/rt-get-sample-info.shader_test \ tests/hlsl/sample-bias.shader_test \ tests/hlsl/sample-cmp.shader_test \ diff --git a/tests/d3d12_test_utils.h b/tests/d3d12_test_utils.h index e48bcbf3..79c8bb69 100644 --- a/tests/d3d12_test_utils.h +++ b/tests/d3d12_test_utils.h @@ -716,7 +716,7 @@ static inline void check_sub_resource_vec4_(unsigned int line, ID3D12Resource *t struct d3d12_resource_readback rb; get_resource_readback_with_command_list(texture, sub_resource_idx, &rb, queue, command_list); - check_readback_data_vec4_(line, &rb.rb, NULL, expected, max_diff); + check_readback_data_vec_(line, &rb.rb, NULL, expected, max_diff, 4); release_resource_readback(&rb); } diff --git a/tests/hlsl/rt-format-mismatch.shader_test b/tests/hlsl/rt-format-mismatch.shader_test new file mode 100644 index 00000000..4b0a28ed --- /dev/null +++ b/tests/hlsl/rt-format-mismatch.shader_test @@ -0,0 +1,199 @@ +[require] +shader model >= 4.0 + +% Let's try to mismatch the shader target output with the RTV type in various +% ways. All of them appears to be valid: the bits are copied as-is, without +% being interpreted. Excessive bits are discarded, missing bits are left +% undefined. The warnings emitted by the native validator suggest that it is +% not an error to rely on these behaviours. + +[rtv 0] +% The default, but just to be explicit. +format r32g32b32a32-float +size (2d, 640, 480) + +[pixel shader] +float4 main() : sv_target +{ + return float4(22.0, -22.0, 1.0e100, -1.0e100); +} + +[test] +draw quad +probe (0, 0) rgba (22.0, -22.0, 1.0e100, -1.0e100) + +[pixel shader] +uint4 main() : sv_target +{ + return uint4(0, 22, 0xfeedcafe, ~0u); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rgbaui (0, 22, 0xfeedcafe, 0xffffffff) + +[pixel shader] +int4 main() : sv_target +{ + return int4(0, 22, -22, -1000); +} + +[test] +todo(mvk & vulkan | glsl) draw quad +todo(mvk) probe (0, 0) rgbai (0, 22, -22, -1000) + +[pixel shader] +float2 main() : sv_target +{ + return float2(22.0, -22.0); +} + +[test] +draw quad +probe (0, 0) rg (22.0, -22.0) + +[rtv 0] +format r32g32b32a32-uint +size (2d, 640, 480) + +[pixel shader] +float4 main() : sv_target +{ + return float4(22.0, -22.0, 1.0e100, -1.0e100); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rgba (22.0, -22.0, 1.0e100, -1.0e100) + +[pixel shader] +uint4 main() : sv_target +{ + return uint4(0, 22, 0xfeedcafe, ~0u); +} + +[test] +draw quad +probe (0, 0) rgbaui (0, 22, 0xfeedcafe, 0xffffffff) + +[pixel shader] +int4 main() : sv_target +{ + return int4(0, 22, -22, -1000); +} + +[test] +todo(mvk & vulkan | glsl) draw quad +todo(mvk) probe (0, 0) rgbai (0, 22, -22, -1000) + +[pixel shader] +float2 main() : sv_target +{ + return float2(22.0, -22.0); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rg (22.0, -22.0) + +[rtv 0] +format r32g32b32a32-sint +size (2d, 640, 480) + +[pixel shader] +float4 main() : sv_target +{ + return float4(22.0, -22.0, 1.0e100, -1.0e100); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rgba (22.0, -22.0, 1.0e100, -1.0e100) + +[pixel shader] +uint4 main() : sv_target +{ + return uint4(0, 22, 0xfeedcafe, ~0u); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rgbaui (0, 22, 0xfeedcafe, 0xffffffff) + +[pixel shader] +int4 main() : sv_target +{ + return int4(0, 22, -22, -1000); +} + +[test] +todo(glsl) draw quad +probe (0, 0) rgbai (0, 22, -22, -1000) + +[pixel shader] +float2 main() : sv_target +{ + return float2(22.0, -22.0); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) rg (22.0, -22.0) + +[rtv 0] +format r32-uint +size (2d, 640, 480) + +[pixel shader] +float4 main() : sv_target +{ + return float4(22.0, -22.0, 1.0e100, -1.0e100); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) r (22.0) + +[pixel shader] +uint4 main() : sv_target +{ + return uint4(22, 0, 0xfeedcafe, ~0u); +} + +[test] +draw quad +probe (0, 0) rui (22) + +[pixel shader] +int4 main() : sv_target +{ + return int4(-22, 22, 0, -1000); +} + +[test] +todo(mvk & vulkan | glsl) draw quad +todo(mvk) probe (0, 0) ri (-22) + +[pixel shader] +float2 main() : sv_target +{ + return float2(22.0, -22.0); +} + +[test] +todo(mvk & vulkan) draw quad +todo(mvk) probe (0, 0) r (22.0) + +% For the avoidance of doubt, 64 bit types cannot be used as target outputs. + +[pixel shader fail] +double2 main() : sv_target +{ + return 0; +} + +[pixel shader fail] +uint64_t2 main() : sv_target +{ + return 0; +} diff --git a/tests/shader_runner.c b/tests/shader_runner.c index daead930..29ff13d4 100644 --- a/tests/shader_runner.c +++ b/tests/shader_runner.c @@ -1138,6 +1138,17 @@ static void parse_test_directive(struct shader_runner *runner, const char *line) ulps = 0; todo_if(runner->is_todo) check_readback_data_vec4(rb, &rect, &v, ulps); } + else if (match_string(line, "rg", &line)) + { + struct vec4 v; + + ret = sscanf(line, "( %f , %f ) %u", &v.x, &v.y, &ulps); + if (ret < 2) + fatal_error("Malformed probe arguments '%s'.\n", line); + if (ret < 3) + ulps = 0; + todo_if(runner->is_todo) check_readback_data_vec2(rb, &rect, &v, ulps); + } else if (match_string(line, "rui", &line) || (is_signed = match_string(line, "ri", &line))) { unsigned int expect; diff --git a/tests/utils.h b/tests/utils.h index 00ca25a4..82f7ec16 100644 --- a/tests/utils.h +++ b/tests/utils.h @@ -203,12 +203,23 @@ static inline bool compare_uvec4(const struct uvec4 *v1, const struct uvec4 *v2) return v1->x == v2->x && v1->y == v2->y && v1->z == v2->z && v1->w == v2->w; } +static inline bool compare_vec(const struct vec4 *v1, const struct vec4 *v2, + unsigned int ulps, unsigned component_count) +{ + if (component_count > 0 && !compare_float(v1->x, v2->x, ulps)) + return false; + if (component_count > 1 && !compare_float(v1->y, v2->y, ulps)) + return false; + if (component_count > 2 && !compare_float(v1->z, v2->z, ulps)) + return false; + if (component_count > 3 && !compare_float(v1->w, v2->w, ulps)) + return false; + return true; +} + static inline bool compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned int ulps) { - return compare_float(v1->x, v2->x, ulps) - && compare_float(v1->y, v2->y, ulps) - && compare_float(v1->z, v2->z, ulps) - && compare_float(v1->w, v2->w, ulps); + return compare_vec(v1, v2, ulps, 4); } static inline void set_rect(RECT *rect, int left, int top, int right, int bottom) @@ -377,9 +388,10 @@ static inline void check_readback_data_uint64_(unsigned int line, struct resourc ok_(line)(all_match, "Got 0x%016"PRIx64", expected 0x%016"PRIx64" at (%u, %u).\n", got, expected, x, y); } -#define check_readback_data_vec4(a, b, c, d) check_readback_data_vec4_(__LINE__, a, b, c, d) -static inline void check_readback_data_vec4_(unsigned int line, const struct resource_readback *rb, - const RECT *rect, const struct vec4 *expected, unsigned int max_diff) +#define check_readback_data_vec2(a, b, c, d) check_readback_data_vec_(__LINE__, a, b, c, d, 2) +#define check_readback_data_vec4(a, b, c, d) check_readback_data_vec_(__LINE__, a, b, c, d, 4) +static inline void check_readback_data_vec_(unsigned int line, const struct resource_readback *rb, + const RECT *rect, const struct vec4 *expected, unsigned int max_diff, unsigned component_count) { RECT r = {0, 0, rb->width, rb->height}; unsigned int x = 0, y = 0; @@ -394,7 +406,7 @@ static inline void check_readback_data_vec4_(unsigned int line, const struct res for (x = r.left; x < r.right; ++x) { got = *get_readback_vec4(rb, x, y); - if (!compare_vec4(&got, expected, max_diff)) + if (!compare_vec(&got, expected, max_diff, component_count)) { all_match = false; break;