-- v3: d3d11/tests: Add a test for NV12 textures.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/d3d11/tests/Makefile.in | 2 +- dlls/d3d11/tests/d3d11.c | 279 +++++++++++++++++++++++++++++++++++ 2 files changed, 280 insertions(+), 1 deletion(-)
diff --git a/dlls/d3d11/tests/Makefile.in b/dlls/d3d11/tests/Makefile.in index 8af7276c427..fbae8aa09c6 100644 --- a/dlls/d3d11/tests/Makefile.in +++ b/dlls/d3d11/tests/Makefile.in @@ -1,5 +1,5 @@ TESTDLL = d3d11.dll -IMPORTS = d3d11 dxgi user32 gdi32 +IMPORTS = d3d11 dxgi user32 gdi32 d3dcompiler
SOURCES = \ d3d11.c diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 24fdb32b829..0249398e255 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -26,6 +26,7 @@ #define COBJMACROS #include "initguid.h" #include "d3d11_4.h" +#include "d3dcompiler.h" #include "winternl.h" #include "wine/wined3d.h" #include "wine/test.h" @@ -130,6 +131,23 @@ struct swapchain_desc DWORD flags; };
+static ID3D10Blob *compile_shader(const char *source, size_t len, const char *profile) +{ + ID3D10Blob *bytecode = NULL, *errors = NULL; + HRESULT hr; + + hr = D3DCompile(source, len, NULL, NULL, NULL, "main", profile, 0, 0, &bytecode, &errors); + ok(hr == S_OK, "Cannot compile shader, hr %#lx.\n", hr); + ok(!!bytecode, "Compilation didn't produce any bytecode.\n"); + if (errors) + { + trace("Compilation errors:\n%s\n", (char *)ID3D10Blob_GetBufferPointer(errors)); + ID3D10Blob_Release(errors); + } + + return bytecode; +} + static void queue_test_entry(const struct test_entry *t) { if (mt_test_count >= mt_tests_size) @@ -1143,6 +1161,40 @@ done: value, expected_value, x, y, z, rb->sub_resource_idx); }
+#define check_readback_data_u8_with_buffer(a, b, c, d) check_readback_data_u8_with_buffer_(__LINE__, a, b, c, d) +static void check_readback_data_u8_with_buffer_(unsigned int line, struct resource_readback *rb, + const char *content, uint32_t depth_pitch, uint32_t slice_pitch) +{ + BYTE value = 0, expected_value = 0; + unsigned int x = 0, y = 0, z = 0; + BOOL all_match = FALSE; + + ok_(__FILE__, line)(rb->map_desc.RowPitch == depth_pitch, "Got row pitch %u instead of %u.\n", + rb->map_desc.RowPitch, depth_pitch); + ok_(__FILE__, line)(rb->map_desc.DepthPitch == slice_pitch, "Got depth pitch %u instead of %u.\n", + rb->map_desc.DepthPitch, depth_pitch); + + for (z = 0; z < rb->depth; ++z) + { + for (y = 0; y < rb->height; ++y) + { + for (x = 0; x < rb->width; ++x) + { + value = get_readback_u8(rb, x, y, z); + expected_value = content[z * slice_pitch + y * depth_pitch + x]; + if (value != expected_value) + goto done; + } + } + } + all_match = TRUE; + +done: + ok_(__FILE__, line)(all_match, + "Got 0x%02x, expected 0x%02x at (%u, %u, %u), sub-resource %u.\n", + value, expected_value, x, y, z, rb->sub_resource_idx); +} + #define check_readback_data_u16(a, b, c, d) check_readback_data_u16_(__LINE__, a, b, c, d) static void check_readback_data_u16_(unsigned int line, struct resource_readback *rb, const RECT *rect, WORD expected_value, BYTE max_diff) @@ -36164,6 +36216,232 @@ static void test_high_resource_count(void) release_test_context(&test_context); }
+static void test_nv12(void) +{ + /* I need only two uints in the cbuffer, but the size must be a multiple of 16. */ + uint32_t cbuffer_data[4], expected_row_pitch, expected_depth_pitch; + D3D11_UNORDERED_ACCESS_VIEW_DESC uav_desc = {0}; + D3D11_SHADER_RESOURCE_VIEW_DESC srv_desc = {0}; + D3D11_SUBRESOURCE_DATA subresource_data = {0}; + D3D11_RENDER_TARGET_VIEW_DESC rtv_desc = {0}; + ID3D11Texture2D *texture, *check_texture; + struct d3d11_test_context test_context; + ID3D11PixelShader *luma_ps, *chroma_ps; + ID3D11UnorderedAccessView *check_uav; + ID3D11RenderTargetView *rtv1, *rtv2; + ID3D11DeviceContext *device_context; + ID3D11ShaderResourceView *srvs[2]; + D3D11_TEXTURE2D_DESC desc = {0}; + struct resource_readback rb; + ID3D11ComputeShader *cs; + ID3D11Buffer *cbuffer; + ID3D10Blob *bytecode; + ID3D11Device *device; + unsigned int i, j; + char *content; + HRESULT hr; + + static const uint32_t clear_values[4] = {0xabcdef00, 0xabcdef00, 0xabcdef00, 0xabcdef00}; + static const float clear_values_float[4] = {100.0, 100.0, 100.0, 100.0}; + static const unsigned int width = 640; + static const unsigned int height = 480; + + static const char cs_code[] = + "Texture2D<uint> luma : register(t0);\n" + "Texture2D<uint2> chroma : register(t1);\n" + "RWTexture2D<uint> check : register(u1);\n" + "\n" + "uint2 size;\n" + "\n" + "[numthreads(1, 1, 1)]\n" + "void main(uint3 threadID : SV_DispatchThreadID)\n" + "{\n" + " const uint2 coords = threadID.xy;\n" + " check[coords] = luma[coords];\n" + " if (any(coords % 2 != 0))\n" + " return;\n" + " const uint2 luma_coords = uint2(coords.x, size.y + coords.y / 2);\n" + " check[luma_coords] = chroma[coords / 2].x;\n" + " check[luma_coords + uint2(1, 0)] = chroma[coords / 2].y;\n" + "}\n"; + + static const char luma_ps_code[] = + "uint main(float4 pos : SV_Position) : SV_Target\n" + "{\n" + " uint2 coords = pos.xy;\n" + " return (coords.y & 7) << 3 | (coords.x & 7);\n" + "}\n"; + + static const char chroma_ps_code[] = + "uint2 main(float4 pos : SV_Position) : SV_Target\n" + "{\n" + " uint2 coords = pos.xy;\n" + " return uint2(1 << 6 | (coords.y & 7) << 3 | (coords.x & 7),\n" + " 1 << 7 | (coords.y & 7) << 3 | (coords.x & 7));\n" + "}\n"; + + expected_row_pitch = width; + expected_depth_pitch = width * height * 3 / 2; + + if (!init_test_context(&test_context, NULL)) + return; + device = test_context.device; + device_context = test_context.immediate_context; + + desc.Width = width; + desc.Height = height; + desc.MipLevels = 1; + desc.ArraySize = 1; + desc.Format = DXGI_FORMAT_NV12; + desc.SampleDesc.Count = 1; + desc.Usage = D3D11_USAGE_DEFAULT; + desc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET; + + content = calloc(width * height * 3 / 2, 1); + ok(!!content, "Failed to allocate memory.\n"); + + for (i = 0; i < height; ++i) + { + for (j = 0; j < width; ++j) + { + unsigned int idx = i * width + j; + + content[idx] = (i & 7) << 3 | (j & 7); + } + } + + for (i = 0; i < height / 2; ++i) + { + for (j = 0; j < width / 2; ++j) + { + unsigned int idx = width * height + i * width + j * 2; + + content[idx] = 1 << 6 | (i & 7) << 3 | (j & 7); + content[idx + 1] = 1 << 7 | (i & 7) << 3 | (j & 7); + } + } + + subresource_data.pSysMem = content; + subresource_data.SysMemPitch = width; + + hr = ID3D11Device_CreateTexture2D(device, &desc, &subresource_data, &texture); + todo_wine + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + if (FAILED(hr)) + { + release_test_context(&test_context); + return; + } + + bytecode = compile_shader(cs_code, sizeof(cs_code) - 1, "cs_5_0"); + hr = ID3D11Device_CreateComputeShader(device, ID3D10Blob_GetBufferPointer(bytecode), + ID3D10Blob_GetBufferSize(bytecode), NULL, &cs); + ID3D10Blob_Release(bytecode); + + bytecode = compile_shader(luma_ps_code, sizeof(luma_ps_code) - 1, "ps_4_0"); + hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(bytecode), + ID3D10Blob_GetBufferSize(bytecode), NULL, &luma_ps); + ID3D10Blob_Release(bytecode); + + bytecode = compile_shader(chroma_ps_code, sizeof(chroma_ps_code) - 1, "ps_4_0"); + hr = ID3D11Device_CreatePixelShader(device, ID3D10Blob_GetBufferPointer(bytecode), + ID3D10Blob_GetBufferSize(bytecode), NULL, &chroma_ps); + ID3D10Blob_Release(bytecode); + + desc.Height += height / 2; + desc.Format = DXGI_FORMAT_R8_UINT; + desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS; + + hr = ID3D11Device_CreateTexture2D(device, &desc, NULL, &check_texture); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + srv_desc.Format = DXGI_FORMAT_R8_UINT; + srv_desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srv_desc.Texture2D.MostDetailedMip = 0; + srv_desc.Texture2D.MipLevels = 1; + + hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srvs[0]); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + srv_desc.Format = DXGI_FORMAT_R8G8_UINT; + + hr = ID3D11Device_CreateShaderResourceView(device, (ID3D11Resource *)texture, &srv_desc, &srvs[1]); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + uav_desc.Format = DXGI_FORMAT_R8_UINT; + uav_desc.ViewDimension = D3D11_UAV_DIMENSION_TEXTURE2D; + uav_desc.Texture2D.MipSlice = 0; + + hr = ID3D11Device_CreateUnorderedAccessView(device, (ID3D11Resource *)check_texture, &uav_desc, &check_uav); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + cbuffer_data[0] = width; + cbuffer_data[1] = height; + + cbuffer = create_buffer(device, D3D11_BIND_CONSTANT_BUFFER, sizeof(cbuffer_data), cbuffer_data); + + ID3D11DeviceContext_ClearUnorderedAccessViewUint(device_context, check_uav, clear_values); + ID3D11DeviceContext_CSSetShader(device_context, cs, NULL, 0); + ID3D11DeviceContext_CSSetShaderResources(device_context, 0, ARRAY_SIZE(srvs), srvs); + ID3D11DeviceContext_CSSetUnorderedAccessViews(device_context, 1, 1, &check_uav, NULL); + ID3D11DeviceContext_CSSetConstantBuffers(device_context, 0, 1, &cbuffer); + ID3D11DeviceContext_Dispatch(device_context, width, height, 1); + + get_texture_readback(check_texture, 0, &rb); + check_readback_data_u8_with_buffer(&rb, content, expected_row_pitch, expected_depth_pitch); + release_resource_readback(&rb); + + rtv_desc.Format = DXGI_FORMAT_R8_UINT; + rtv_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D; + rtv_desc.Texture2D.MipSlice = 0; + + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv1); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + rtv_desc.Format = DXGI_FORMAT_R8G8_UINT; + + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)texture, &rtv_desc, &rtv2); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ID3D11DeviceContext_ClearRenderTargetView(device_context, rtv1, clear_values_float); + set_viewport(device_context, 0.0, 0.0, width, height, 0.0, 1.0); + ID3D11DeviceContext_OMSetRenderTargets(device_context, 1, &rtv1, NULL); + ID3D11DeviceContext_PSSetShader(device_context, luma_ps, NULL, 0); + draw_quad(&test_context); + + ID3D11DeviceContext_ClearRenderTargetView(device_context, rtv2, clear_values_float); + set_viewport(device_context, 0.0, 0.0, width, height, 0.0, 1.0); + ID3D11DeviceContext_OMSetRenderTargets(device_context, 1, &rtv2, NULL); + ID3D11DeviceContext_PSSetShader(device_context, chroma_ps, NULL, 0); + draw_quad(&test_context); + + ID3D11DeviceContext_ClearUnorderedAccessViewUint(device_context, check_uav, clear_values); + ID3D11DeviceContext_CSSetShader(device_context, cs, NULL, 0); + ID3D11DeviceContext_CSSetShaderResources(device_context, 0, ARRAY_SIZE(srvs), srvs); + ID3D11DeviceContext_CSSetUnorderedAccessViews(device_context, 1, 1, &check_uav, NULL); + ID3D11DeviceContext_CSSetConstantBuffers(device_context, 0, 1, &cbuffer); + ID3D11DeviceContext_Dispatch(device_context, width, height, 1); + + get_texture_readback(check_texture, 0, &rb); + check_readback_data_u8_with_buffer(&rb, content, expected_row_pitch, expected_depth_pitch); + release_resource_readback(&rb); + + ID3D11RenderTargetView_Release(rtv2); + ID3D11RenderTargetView_Release(rtv1); + ID3D11Buffer_Release(cbuffer); + ID3D11UnorderedAccessView_Release(check_uav); + ID3D11ShaderResourceView_Release(srvs[1]); + ID3D11ShaderResourceView_Release(srvs[0]); + ID3D11Texture2D_Release(check_texture); + free(content); + ID3D11PixelShader_Release(chroma_ps); + ID3D11PixelShader_Release(luma_ps); + ID3D11ComputeShader_Release(cs); + ID3D11Texture2D_Release(texture); + release_test_context(&test_context); +} + START_TEST(d3d11) { unsigned int argc, i; @@ -36363,6 +36641,7 @@ START_TEST(d3d11) queue_test(test_clear_during_render); queue_test(test_stencil_export); queue_test(test_high_resource_count); + queue_test(test_nv12);
run_queued_tests();
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The tests also ran into some preexisting test failures. If you know how to fix them that would be helpful. See the TestBot job for the details:
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=146080
Your paranoid android.
=== w7u_2qxl (32 bit report) ===
d3d11: d3d11.c:36329: Test failed: Got hr 0x80070057.
=== w7u_adm (32 bit report) ===
d3d11: d3d11.c:36329: Test failed: Got hr 0x80070057.
=== w7u_el (32 bit report) ===
d3d11: d3d11.c:36329: Test failed: Got hr 0x80070057.
=== w8 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x01 at (1, 0, 0), sub-resource 0.
=== w8adm (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x01 at (1, 0, 0), sub-resource 0.
=== w864 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x01 at (1, 0, 0), sub-resource 0.
=== w1064v1507 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064v1809 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064_tsign (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64_en_AE_u8 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w11pro64 (32 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w7pro64 (64 bit report) ===
d3d11: d3d11.c:36329: Test failed: Got hr 0x80070057.
=== w864 (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x01 at (1, 0, 0), sub-resource 0.
=== w1064v1507 (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064v1809 (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064_2qxl (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064_adm (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w1064_tsign (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64 (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64_ar (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64_ja (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w10pro64_zh_CN (64 bit report) ===
d3d11: d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
=== w11pro64_amd (64 bit report) ===
d3d11: d3d11.c:36392: Test failed: Got row pitch 768 instead of 640. d3d11.c:36392: Test failed: Got depth pitch 552960 instead of 640. d3d11.c:36427: Test failed: Got row pitch 768 instead of 640. d3d11.c:36427: Test failed: Got depth pitch 552960 instead of 640. d3d11.c:36427: Test failed: Got 0x00, expected 0x40 at (0, 480, 0), sub-resource 0.
On Wed Jun 5 08:47:37 2024 +0000, Elizabeth Figura wrote:
This is fine, although the slightly unfortunate thing about writing the test this way is that you can't see what the actual texture contents are if they're wrong. I.e. could we instead just write the loaded values directly into the UAV/RTV and check them on CPU?
Good point, done. I didn't explicitly test UAVs, trusting that they behave like SRVs in terms of mapping view coordinates to texture coordinates.