NVIDIA and AMD round differently the assignment of 0.5f to a UAV of type R16G16_UNORM. NVIDIA rounds to 0x7fff and AMD to 0x8000. According to both Vulkan and D3D12 specifications, both values are acceptable, but the discrepancy currently appears as a failure on NVIDIA cards.
Work around the issue by using 0.25f instead of 0.5f, which is rounded as 0x4000 on both implementations.
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- tests/d3d12.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 5067dd97..46de3316 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -4930,7 +4930,7 @@ static void test_clear_unordered_access_view_buffer(void) {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x1234, 0xabcd, 0, 0}, 0xabcd1234}, {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, - {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff8000, true}, + {0x3e800000 /* 0.25f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff4000, true}, {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, {0x40000000 /* 2.0f */, 0 /* 0.0f */, 0, 0}, 0x0000ffff, true}, {DXGI_FORMAT_R16G16_UNORM, { 0, BUFFER_SIZE / sizeof(uint32_t), 0, 0, D3D12_BUFFER_UAV_FLAG_NONE}, @@ -5124,7 +5124,7 @@ static void test_clear_unordered_access_view_image(void) {DXGI_FORMAT_R11G11B10_FLOAT, 1, 1, 0, 0, 1, 0, {}, {1, 2, 3, 4}, 0x00c01001}, /* Test float clears with formats. */ {DXGI_FORMAT_R16G16_UNORM, 1, 1, 0, 0, 1, 0, {}, - {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff8000, true}, + {0x3e800000 /* 0.25f */, 0x3f800000 /* 1.0f */, 0, 0}, 0xffff4000, true}, {DXGI_FORMAT_R16G16_FLOAT, 1, 1, 0, 0, 1, 0, {}, {0x3f000000 /* 0.5f */, 0x3f800000 /* 1.0f */, 0, 0}, 0x3c003800, true}, {DXGI_FORMAT_R8G8B8A8_UNORM, 1, 1, 0, 0, 1, 0, {},
D3D mandates that NaN becomes zero when converted to unsigned[1], while it doesn't look like that SPIR-V's OpConvertFToU has a similar provision[2]. In practice, this seems to work on AMD and fails on NVIDIA, where 0x80000000 is produced instead.
[1] https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec... [2] https://www.khronos.org/registry/SPIR-V/specs/unified1/SPIRV.html#Conversion
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- tests/d3d12.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 46de3316..5d42a26e 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -9939,6 +9939,7 @@ static void test_shader_instructions(void) bool is_float64; bool is_todo; bool skip_on_warp; + bool todo_on_nvidia; } uint_tests[] = { @@ -10187,8 +10188,8 @@ static void test_shader_instructions(void) {&ps_dge, {.d = {{1.5, 1.0}}}, {{0xffffffff}}, true}, {&ps_dlt, {.d = {{0.0, 1.0}}}, {{0xffffffff}}, true}, {&ps_dlt, {.d = {{1.0, 1.0}}}, {{0x00000000}}, true}, - {&ps_dtou, {.d = {{ -NAN}}}, {{ 0, 0 }}, true}, - {&ps_dtou, {.d = {{ NAN}}}, {{ 0, 0 }}, true}, + {&ps_dtou, {.d = {{ -NAN}}}, {{ 0, 0 }}, true, false, false, true}, + {&ps_dtou, {.d = {{ NAN}}}, {{ 0, 0 }}, true, false, false, true}, {&ps_dtou, {.d = {{-INFINITY}}}, {{ 0, ~0u}}, true}, {&ps_dtou, {.d = {{ INFINITY}}}, {{~0u, 0 }}, true}, {&ps_dtou, {.d = {{ -1.0}}}, {{ 0, 1 }}, true}, @@ -10605,6 +10606,7 @@ static void test_shader_instructions(void)
transition_resource_state(command_list, context.render_target, D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_COPY_SOURCE); + todo_if(uint_tests[i].todo_on_nvidia && is_nvidia_device(context.device)) check_sub_resource_uvec4(context.render_target, 0, queue, command_list, &uint_tests[i].output.u);
reset_command_list(command_list, context.allocator);
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com
They seem to work with mesa 21.3.7. Since some developers are using older releases where the bug is not yet fixed, I am leaving it marked as a bug.
Signed-off-by: Giovanni Mascellani gmascellani@codeweavers.com --- tests/d3d12.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/tests/d3d12.c b/tests/d3d12.c index 5d42a26e..0abdb7b9 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -23057,7 +23057,6 @@ static void test_atomic_instructions(void) ID3D12CommandQueue *queue; ID3D12Device *device; unsigned int i, j; - bool is_todo; HRESULT hr;
static const DWORD ps_atomics_code[] = @@ -23267,12 +23266,13 @@ static void test_atomic_instructions(void) { unsigned int value = get_readback_uint(&rb, j, 0, 0); unsigned int expected = test->expected_result[j]; + bool is_bug;
- is_todo = test->i.x < 0 + is_bug = test->i.x < 0 && (!strcmp(instructions[j], "atomic_imax") || !strcmp(instructions[j], "atomic_imin"));
- bug_if(is_todo && is_nvidia_device(device)) - todo_if(is_todo) + /* Fixed at least on radv with mesa >= 21.3.7. */ + bug_if(is_bug) ok(value == expected, "Test %u: Got %#x (%d), expected %#x (%d) for '%s' " "with inputs (%u, %u), (%d), %#x (%d).\n", i, value, value, expected, expected, instructions[j], @@ -23286,13 +23286,13 @@ static void test_atomic_instructions(void) get_buffer_readback_with_command_list(cs_buffer, DXGI_FORMAT_R32_UINT, &rb, queue, command_list); for (j = 0; j < ARRAY_SIZE(instructions); ++j) { - bool todo_instruction = !strcmp(imm_instructions[j], "imm_atomic_imax") + bool bug_instruction = !strcmp(imm_instructions[j], "imm_atomic_imax") || !strcmp(imm_instructions[j], "imm_atomic_imin"); unsigned int value = get_readback_uint(&rb, j, 0, 0); unsigned int expected = test->expected_result[j];
- bug_if(test->i.x < 0 && todo_instruction && is_nvidia_device(device)) - todo_if(test->i.x < 0 && todo_instruction) + /* Fixed at least on radv with mesa >= 21.3.7. */ + bug_if(test->i.x < 0 && bug_instruction) ok(value == expected, "Test %u: Got %#x (%d), expected %#x (%d) for '%s' " "with inputs (%u, %u), (%d), %#x (%d).\n", i, value, value, expected, expected, imm_instructions[j],
Signed-off-by: Henri Verbeet hverbeet@codeweavers.com