This one checks results of blending of background and foreground samples, and a wider variety of pixel formats.
Signed-off-by: Jan Sikorski jsikorski@codeweavers.com --- dlls/d3d11/tests/d3d11.c | 325 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 325 insertions(+)
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c index 6cdac34c0cd..f0bdd26a948 100644 --- a/dlls/d3d11/tests/d3d11.c +++ b/dlls/d3d11/tests/d3d11.c @@ -260,6 +260,13 @@ static BOOL compare_vec4(const struct vec4 *v1, const struct vec4 *v2, unsigned && compare_float(v1->w, v2->w, ulps); }
+static BOOL compare_int(int x, int y, int max_diff) +{ + int diff = x > y ? x - y : y - x; + + return diff <= max_diff; +} + static BOOL compare_uint(unsigned int x, unsigned int y, unsigned int max_diff) { unsigned int diff = x > y ? x - y : y - x; @@ -280,6 +287,15 @@ static BOOL compare_color(DWORD c1, DWORD c2, BYTE max_diff) && compare_uint((c1 >> 24) & 0xff, (c2 >> 24) & 0xff, max_diff); }
+static BOOL compare_scolor(DWORD c1, DWORD c2, BYTE max_diff) +{ + signed char c1x = c1, c1y = (c1 >> 8), c1z = (c1 >> 16), c1w = (c1 >> 24); + signed char c2x = c2, c2y = (c2 >> 8), c2z = (c2 >> 16), c2w = (c2 >> 24); + + return compare_int(c1x, c2x, max_diff) && compare_int(c1y, c2y, max_diff) + && compare_int(c1z, c2z, max_diff) && compare_int(c1w, c2w, max_diff); +} + static char const *debugstr_viewport(D3D11_VIEWPORT *vp) { if (!vp) return "(null)"; @@ -30057,6 +30073,314 @@ done: release_test_context(&test_context); }
+static void test_multisample_resolve_blended(void) +{ + static const D3D11_VIEWPORT viewport = { 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f }; + static const float clear_color[4] = {0.2f, 0.2f, 0.2f, 1.0f}; + unsigned int vertex_buffer_stride = 6 * sizeof(float); + ID3D11PixelShader *pixel_shader, *pixel_shader_uint; + ID3D11Texture2D *resolve_target, *render_target; + D3D11_RENDER_TARGET_VIEW_DESC render_view_desc; + ID3D11RenderTargetView *render_target_view; + unsigned int vertex_buffer_offset = 0; + ID3D11DeviceContext *device_context; + D3D11_TEXTURE2D_DESC texture_desc; + ID3D11VertexShader *vertex_shader; + ID3D11InputLayout *input_layout; + unsigned int i, quality_levels; + struct resource_readback rb; + ID3D11Buffer *vertex_buffer; + unsigned char *result; + ID3D11Device *device; + BOOL compare_ok; + HRESULT hr; + + static const DWORD vs_code[] = + { +#if 0 + struct VS_Input + { + float2 pos : TEXCOORD0; + float4 color : COLOR; + }; + + struct VS_Output + { + float4 position : SV_POSITION; + float4 color : COLOR; + }; + + VS_Output vs_main(VS_Input input) + { + VS_Output output; + output.position = float4(input.pos, 0.0f, 1.0f); + output.color = input.color; + + return output; + } +#endif + 0x43425844, 0x3fbe97c7, 0x2cdce39d, 0xa8d3bf48, 0xe0d872e3, 0x00000001, 0x00000160, 0x00000003, + 0x0000002c, 0x0000007c, 0x000000d0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000303, 0x00000041, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x43584554, 0x44524f4f, 0x4c4f4300, 0xab00524f, 0x4e47534f, + 0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000, + 0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653, + 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000088, 0x00010040, 0x00000022, + 0x0300005f, 0x00101032, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2, + 0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x00102032, 0x00000000, + 0x00101046, 0x00000000, 0x08000036, 0x001020c2, 0x00000000, 0x00004002, 0x00000000, 0x00000000, + 0x00000000, 0x3f800000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e, + }; + + static const DWORD ps_code[] = + { +#if 0 + float4 ps_main(VS_Output input) : SV_TARGET + { + return input.color; + } +#endif + 0x43425844, 0xe2087fa6, 0xa35fbd95, 0x8e585b3f, 0x67890f54, 0x00000001, 0x000000f4, 0x00000003, + 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000003, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000038, 0x00000040, + 0x0000000e, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x05000036, + 0x001020f2, 0x00000000, 0x00101e46, 0x00000001, 0x0100003e + }; + + static const DWORD ps_uint_code[] = + { +#if 0 + uint4 ps_main_uint(VS_Output input) : SV_TARGET + { + return 255 * input.color; + } +#endif + 0x43425844, 0x9c2c834b, 0x37ca7b30, 0x01b4b43e, 0x713b001e, 0x00000001, 0x00000124, 0x00000003, + 0x0000002c, 0x00000080, 0x000000b4, 0x4e475349, 0x0000004c, 0x00000002, 0x00000008, 0x00000038, + 0x00000000, 0x00000001, 0x00000003, 0x00000000, 0x0000000f, 0x00000044, 0x00000000, 0x00000000, + 0x00000003, 0x00000001, 0x00000f0f, 0x505f5653, 0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, + 0x4e47534f, 0x0000002c, 0x00000001, 0x00000008, 0x00000020, 0x00000000, 0x00000000, 0x00000001, + 0x00000000, 0x0000000f, 0x545f5653, 0x45475241, 0xabab0054, 0x52444853, 0x00000068, 0x00000040, + 0x0000001a, 0x03001062, 0x001010f2, 0x00000001, 0x03000065, 0x001020f2, 0x00000000, 0x02000068, + 0x00000001, 0x0a000038, 0x001000f2, 0x00000000, 0x00101e46, 0x00000001, 0x00004002, 0x437f0000, + 0x437f0000, 0x437f0000, 0x437f0000, 0x0500001c, 0x001020f2, 0x00000000, 0x00100e46, 0x00000000, + 0x0100003e + }; + + static const struct + { + struct vec2 xy; + struct vec4 rgba; + } + vertex_data[] = + { + {{ 1.0f, 1.0f }, { .8f, 0.f, 0.f, 1.f }}, + {{ 1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }}, + {{-1.0f, -1.0f }, { .8f, 0.f, 0.f, 1.f }}, + }; + + static const D3D11_INPUT_ELEMENT_DESC input_elements[] = + { + { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }, + { "COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0 } + }; + + static const struct + { + BOOL use_uint_shader; + DXGI_FORMAT render_target_view_format; + DXGI_FORMAT source_format; + DXGI_FORMAT destination_format; + DXGI_FORMAT resolve_format; + unsigned int byte_count; + unsigned char expected[4]; + BOOL todo; + } + tests[] = + { + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f } }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_FLOAT, + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_R32_TYPELESS, + DXGI_FORMAT_R32_TYPELESS, DXGI_FORMAT_R32_FLOAT, + 4, { 0, 0, 0, 0x3f }, TRUE }, + { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, + DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_UNORM, + 2, { 0, 0x80 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_FLOAT, + 2, { 0xff, 0x37 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, + 2, { 0xff, 0x37 } }, + { FALSE, DXGI_FORMAT_R16_FLOAT, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_UNORM, + 2, { 0x66, 0x36 }, TRUE }, + { FALSE, DXGI_FORMAT_R16_UNORM, DXGI_FORMAT_R16_TYPELESS, + DXGI_FORMAT_R16_TYPELESS, DXGI_FORMAT_R16_FLOAT, + 2, { 0xbd, 0xc8 } }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x80, 0x19, 0x19, 0xff } }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + 4, { 0x99, 0x23, 0x23, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, + 4, { 0, 0x19, 0x19, 0xff }, TRUE }, + { FALSE, DXGI_FORMAT_R8G8B8A8_SNORM, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x3f, 0xc, 0xc, 0x7f }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x3f, 0, 0, 0x40 }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_SINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_SNORM, + 4, { 0x40, 0, 0, 0x40 }, TRUE }, + { TRUE, DXGI_FORMAT_R8G8B8A8_UINT, DXGI_FORMAT_R8G8B8A8_TYPELESS, + DXGI_FORMAT_R8G8B8A8_TYPELESS, DXGI_FORMAT_R8G8B8A8_UNORM, + 4, { 0x66, 0, 0, 0x80 }, TRUE }, + }; + + texture_desc.Width = 1; + texture_desc.Height = 1; + texture_desc.MipLevels = 1; + texture_desc.ArraySize = 1; + texture_desc.SampleDesc.Quality = 0; + texture_desc.MiscFlags = 0; + + render_view_desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2DMS; + + if (!(device = create_device(NULL))) + { + skip("Failed to create device.\n"); + return; + } + + ID3D11Device_GetImmediateContext(device, &device_context); + + hr = ID3D11Device_CreateVertexShader(device, vs_code, sizeof(vs_code), + NULL, &vertex_shader); + ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreatePixelShader(device, ps_code, sizeof(ps_code), + NULL, &pixel_shader); + ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreatePixelShader(device, ps_uint_code, sizeof(ps_uint_code), + NULL, &pixel_shader_uint); + ok(SUCCEEDED(hr),"Failed to create uint pixel shader, hr %#x.\n", hr); + + hr = ID3D11Device_CreateInputLayout(device, input_elements, + ARRAY_SIZE(input_elements), vs_code, sizeof(vs_code), &input_layout); + ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr); + + vertex_buffer = create_buffer(device, D3D11_BIND_VERTEX_BUFFER, + sizeof(vertex_data), vertex_data); + + ID3D11DeviceContext_IASetVertexBuffers(device_context, 0, 1, &vertex_buffer, + &vertex_buffer_stride, &vertex_buffer_offset); + ID3D11DeviceContext_IASetPrimitiveTopology(device_context, D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST); + ID3D11DeviceContext_IASetInputLayout(device_context, input_layout); + ID3D11DeviceContext_VSSetShader(device_context, vertex_shader, NULL, 0); + ID3D11DeviceContext_RSSetViewports(device_context, 1, &viewport); + + for (i = 0; i < ARRAY_SIZE(tests); ++i) + { + hr = ID3D11Device_CheckMultisampleQualityLevels(device, tests[i].source_format, 2, &quality_levels); + ok(SUCCEEDED(hr), "Failed to check multisample quality levels, hr %#x.\n", hr); + if (!quality_levels) + { + skip("Test %3u: 2xMSAA not supported.\n", i); + continue; + } + + texture_desc.Format = tests[i].source_format; + texture_desc.SampleDesc.Count = 2; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = D3D11_BIND_RENDER_TARGET; + texture_desc.CPUAccessFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &render_target); + ok(SUCCEEDED(hr), "Failed to create render target texture, hr %#x.\n", hr); + + texture_desc.Format = tests[i].destination_format; + texture_desc.SampleDesc.Count = 1; + texture_desc.Usage = D3D11_USAGE_DEFAULT; + texture_desc.BindFlags = 0; + texture_desc.CPUAccessFlags = 0; + hr = ID3D11Device_CreateTexture2D(device, &texture_desc, NULL, &resolve_target); + ok(SUCCEEDED(hr), "Failed to create resolve texture, hr %#x.\n", hr); + + render_view_desc.Format = tests[i].render_target_view_format; + hr = ID3D11Device_CreateRenderTargetView(device, (ID3D11Resource *)render_target, + &render_view_desc, &render_target_view); + ok(SUCCEEDED(hr), "Failed to create render target view, hr %#x.\n", hr); + + ID3D11DeviceContext_RSSetViewports(device_context, 1, &viewport); + ID3D11DeviceContext_OMSetRenderTargets(device_context, 1, &render_target_view, NULL); + ID3D11DeviceContext_PSSetShader(device_context, tests[i].use_uint_shader ? pixel_shader_uint : pixel_shader, NULL, 0); + ID3D11DeviceContext_ClearRenderTargetView(device_context, render_target_view, clear_color); + ID3D11DeviceContext_Draw(device_context, 3, 0); + ID3D11DeviceContext_ResolveSubresource(device_context, (ID3D11Resource *)resolve_target, + 0, (ID3D11Resource *)render_target, 0, tests[i].resolve_format); + + get_texture_readback(resolve_target, 0, &rb); + result = get_readback_data(&rb, 0, 0, 0, tests[i].byte_count); + + switch (tests[i].resolve_format) + { + case DXGI_FORMAT_R32_FLOAT: + compare_ok = compare_float(*(float *)result, *(float *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R16_UNORM: + case DXGI_FORMAT_R16_FLOAT: + compare_ok = compare_uint(*(WORD *)result, *(WORD *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R8G8B8A8_UNORM: + case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB: + compare_ok = compare_color(*(DWORD *)result, *(DWORD *)tests[i].expected, 2); + break; + case DXGI_FORMAT_R8G8B8A8_SNORM: + compare_ok = compare_scolor(*(DWORD *)result, *(DWORD *)tests[i].expected, 2); + break; + default: + trace("Test %3u: unhandled format.\n", i); + compare_ok = FALSE; + break; + } + + todo_wine_if(tests[i].todo) + ok(compare_ok, "Test %3u: expected: %2x %2x %2x %2x, got: %2x %2x %2x %2x.\n", i, + tests[i].expected[0], tests[i].expected[1], tests[i].expected[2], tests[i].expected[3], + result[0], result[1], result[2], result[3]); + + release_resource_readback(&rb); + ID3D11RenderTargetView_Release(render_target_view); + ID3D11Texture2D_Release(render_target); + ID3D11Texture2D_Release(resolve_target); + } + + ID3D11Buffer_Release(vertex_buffer); + ID3D11InputLayout_Release(input_layout); + ID3D11PixelShader_Release(pixel_shader_uint); + ID3D11PixelShader_Release(pixel_shader); + ID3D11VertexShader_Release(vertex_shader); + ID3D11DeviceContext_Release(device_context); + ID3D11Device_Release(device); +} + static void test_multisample_resolve(void) { struct d3d11_test_context test_context; @@ -32284,6 +32608,7 @@ START_TEST(d3d11) queue_test(test_unbound_multisample_texture); queue_test(test_multiple_viewports); queue_test(test_multisample_resolve); + queue_test(test_multisample_resolve_blended); queue_test(test_sample_shading); queue_test(test_sample_mask); queue_test(test_depth_clip);