[PATCH 5/6] d3d10core/tests: Add visual tests for locking vertexbuffers

Patrick Rudolph siro at das-labor.org
Tue Jul 26 12:09:10 CDT 2016


Test flags D3D10_MAP_WRITE_NO_OVERWRITE and D3D10_MAP_WRITE_DISCARD
on staging and dynamic vertexbuffers. After submitting a draw call
the used vertexbuffer is mapped and modified. The visual result
changes depending on used flags. As this test depends on race conditions
the buffer size is calibrated first to allow the test to pass on
fast and slow machines.

Test have been done on the following test system:
* Nvidia Ion on Windows 7
* AMD Radeon Mobility HD4300 Series on Windows 7
* Nvidia Quadro NVS 140M on Windows 8

The test isn't reliable yet.

The flag D3D10_MAP_WRITE_NO_OVERWRITE has only effect on dynamic buffers.

Signed-off-by: Patrick Rudolph <siro at das-labor.org>
---
 dlls/d3d10core/tests/device.c | 310 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 310 insertions(+)

diff --git a/dlls/d3d10core/tests/device.c b/dlls/d3d10core/tests/device.c
index 9b3a943..1f78ae4 100644
--- a/dlls/d3d10core/tests/device.c
+++ b/dlls/d3d10core/tests/device.c
@@ -8853,6 +8853,315 @@ static void test_uint_shader_instructions(void)
     release_test_context(&test_context);
 }
 
+static void test_vb_lock_flags(void)
+{
+    struct d3d10core_test_context test_context;
+    D3D10_SUBRESOURCE_DATA resource_data;
+    ID3D10InputLayout *input_layout;
+    DWORD color, primitives, size;
+    D3D10_BUFFER_DESC buffer_desc;
+    ULONG timestamp1, timestamp2;
+    unsigned int stride, offset;
+    ID3D10VertexShader *vs;
+    ID3D10PixelShader *ps;
+    ID3D10Device *device;
+    BOOL unsyncronized;
+    ID3D10Buffer *vb;
+    HRESULT hr;
+    int i;
+
+    static const struct {
+        const char* flags_s;
+        DWORD flags;
+        HRESULT hr;
+        BOOL unsyncronized;
+        BOOL todo;
+        BOOL broken;
+    } staging_tests[] =
+    {
+        {"0", 0, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_WRITE", D3D10_MAP_WRITE, S_OK, FALSE, FALSE, FALSE},
+        {"D3D10_MAP_READ", D3D10_MAP_READ, S_OK, FALSE, FALSE, TRUE},
+        {"D3D10_MAP_READ_WRITE", D3D10_MAP_READ_WRITE, S_OK, FALSE, FALSE, FALSE},
+        {"D3D10_MAP_WRITE_DISCARD", D3D10_MAP_WRITE_DISCARD, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_WRITE_NO_OVERWRITE", D3D10_MAP_WRITE_NO_OVERWRITE, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_WRITE_DISCARD | D3D10_MAP_WRITE_NO_OVERWRITE",
+                D3D10_MAP_WRITE_DISCARD | D3D10_MAP_WRITE_NO_OVERWRITE, E_INVALIDARG, FALSE, TRUE, FALSE},
+    }, dynamic_tests[] =
+    {
+        {"0", 0, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_WRITE", D3D10_MAP_WRITE, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_READ", D3D10_MAP_READ, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_READ_WRITE", D3D10_MAP_READ_WRITE, E_INVALIDARG, FALSE, TRUE, FALSE},
+        {"D3D10_MAP_WRITE_DISCARD", D3D10_MAP_WRITE_DISCARD, S_OK, FALSE, FALSE, FALSE},
+        {"D3D10_MAP_WRITE_NO_OVERWRITE", D3D10_MAP_WRITE_NO_OVERWRITE, S_OK, TRUE, FALSE, FALSE},
+        {"D3D10_MAP_WRITE_DISCARD | D3D10_MAP_WRITE_NO_OVERWRITE",
+                D3D10_MAP_WRITE_DISCARD | D3D10_MAP_WRITE_NO_OVERWRITE, S_OK, TRUE, FALSE, FALSE},
+    };
+
+    static const DWORD vs_code[] =
+    {
+#if 0
+        struct vs_out
+        {
+            float4 position : SV_POSITION;
+            float4 color : COLOR;
+        };
+
+        struct vs_out main(float4 position : POSITION, float4 color : COLOR)
+        {
+            struct vs_out o;
+
+            o.position = position;
+            o.color = color;
+
+            return o;
+        }
+#endif
+        0x43425844, 0x5c73b061, 0x5c71125f, 0x3f8b345f, 0xce04b9ab, 0x00000001, 0x00000140, 0x00000003,
+        0x0000002c, 0x0000007c, 0x000000d0, 0x4e475349, 0x00000048, 0x00000002, 0x00000008, 0x00000038,
+        0x00000000, 0x00000000, 0x00000003, 0x00000000, 0x00000f0f, 0x00000041, 0x00000000, 0x00000000,
+        0x00000003, 0x00000001, 0x00000f0f, 0x49534f50, 0x4e4f4954, 0x4c4f4300, 0xab00524f, 0x4e47534f,
+        0x0000004c, 0x00000002, 0x00000008, 0x00000038, 0x00000000, 0x00000001, 0x00000003, 0x00000000,
+        0x0000000f, 0x00000044, 0x00000000, 0x00000000, 0x00000003, 0x00000001, 0x0000000f, 0x505f5653,
+        0x5449534f, 0x004e4f49, 0x4f4c4f43, 0xabab0052, 0x52444853, 0x00000068, 0x00010040, 0x0000001a,
+        0x0300005f, 0x001010f2, 0x00000000, 0x0300005f, 0x001010f2, 0x00000001, 0x04000067, 0x001020f2,
+        0x00000000, 0x00000001, 0x03000065, 0x001020f2, 0x00000001, 0x05000036, 0x001020f2, 0x00000000,
+        0x00101e46, 0x00000000, 0x05000036, 0x001020f2, 0x00000001, 0x00101e46, 0x00000001, 0x0100003e,
+    };
+    static const DWORD ps_code[] =
+    {
+#if 0
+        struct vs_out
+        {
+            float4 position : SV_POSITION;
+            float4 color : COLOR;
+        };
+
+        float4 main(struct vs_out i) : SV_TARGET
+        {
+            return i.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,
+    };
+
+    struct quad
+    {
+        struct
+        {
+            struct vec3 position;
+            DWORD diffuse;
+        } strip[4];
+    };
+    static const struct quad quad1 =
+    {
+        {
+            {{-1.0f, -1.0f, 0.0f}, 0xffff0000},
+            {{-1.0f,  1.0f, 0.0f}, 0xff00ff00},
+            {{ 1.0f, -1.0f, 0.0f}, 0xff0000ff},
+            {{ 1.0f,  1.0f, 0.0f}, 0xffffffff},
+        }
+    }, quad2 =
+    {
+        {
+            {{-1.0f, -1.0f, 0.0f}, 0xffffff00},
+            {{-1.0f,  1.0f, 0.0f}, 0xffffff00},
+            {{ 1.0f, -1.0f, 0.0f}, 0xffffff00},
+            {{ 1.0f,  1.0f, 0.0f}, 0xffffff00},
+        }
+    };
+    struct quad *quads;
+
+    static const D3D10_INPUT_ELEMENT_DESC layout_desc[] =
+    {
+        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0,  0, D3D11_INPUT_PER_VERTEX_DATA, 0},
+        {"COLOR",    0, DXGI_FORMAT_R8G8B8A8_UNORM,  0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
+    };
+    static const float black[] = {0.0f, 0.0f, 0.0f, 0.0f};
+
+    if (!init_test_context(&test_context))
+          return;
+
+    device = test_context.device;
+
+    hr = ID3D10Device_CreateInputLayout(device, layout_desc, sizeof(layout_desc) / sizeof(*layout_desc),
+            vs_code, sizeof(vs_code), &input_layout);
+    ok(SUCCEEDED(hr), "Failed to create input layout, hr %#x.\n", hr);
+
+    hr = ID3D10Device_CreateVertexShader(device, vs_code, sizeof(vs_code), &vs);
+    ok(SUCCEEDED(hr), "Failed to create vertex shader, hr %#x.\n", hr);
+    hr = ID3D10Device_CreatePixelShader(device, ps_code, sizeof(ps_code), &ps);
+    ok(SUCCEEDED(hr), "Failed to create pixel shader, hr %#x.\n", hr);
+
+    size = 0x1000;
+    /* Allocate memory to initialize the buffer */
+    resource_data.pSysMem = HeapAlloc(GetProcessHeap(), 0, size);
+    resource_data.SysMemPitch = 0;
+    resource_data.SysMemSlicePitch = 0;
+
+    if (!resource_data.pSysMem)
+        return;
+
+    quads = (void *)resource_data.pSysMem;
+    for (i = 0; i < size / sizeof(quad1); i++)
+        quads[i] = quad1;
+
+    /* Calculate number of primitives in buffer quads[] */
+    stride = sizeof(quad1.strip[0]);
+    primitives = size / stride;
+    offset = 0;
+
+    buffer_desc.ByteWidth = size;
+    buffer_desc.Usage = D3D10_USAGE_STAGING;
+    buffer_desc.BindFlags = 0;
+    buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE | D3D10_CPU_ACCESS_READ;
+    buffer_desc.MiscFlags = 0;
+
+    hr = ID3D10Device_CreateBuffer(device, &buffer_desc, &resource_data, &vb);
+    ok(SUCCEEDED(hr), "Failed to create vertexbuffer.\n");
+
+    ID3D10Device_IASetInputLayout(device, input_layout);
+    ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+    ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &stride, &offset);
+    ID3D10Device_VSSetShader(device, vs);
+    ID3D10Device_PSSetShader(device, ps);
+
+    ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, black);
+
+    timestamp1 = GetTickCount();
+
+    ID3D10Device_Draw(device, primitives, 0);
+
+    timestamp2 = GetTickCount();
+
+    /* Adjust buffer size for 1 second draw call duration */
+    size = (size * 1000UL) / (timestamp2 - timestamp1 + 1);
+
+    ID3D10Buffer_Release(vb);
+    HeapFree(GetProcessHeap(), 0, (void *)resource_data.pSysMem);
+
+    resource_data.pSysMem = HeapAlloc(GetProcessHeap(), 0, size);
+    if (!resource_data.pSysMem)
+        return;
+
+    quads = (void *)resource_data.pSysMem;
+    for (i = 0; i < size / sizeof(quad1); i++)
+        quads[i] = quad1;
+
+    /* Calculate number of primitives in buffer quads[] */
+    stride = sizeof(quad1.strip[0]);
+    primitives = size / stride;
+    offset = 0;
+
+    buffer_desc.ByteWidth = size;
+
+    for(i = 0; i < sizeof(staging_tests)/sizeof(staging_tests[0]); i++)
+    {
+        hr = ID3D10Device_CreateBuffer(device, &buffer_desc, &resource_data, &vb);
+        ok(SUCCEEDED(hr), "Failed to create vertexbuffer.\n");
+
+        ID3D10Device_IASetInputLayout(device, input_layout);
+        ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+        ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &stride, &offset);
+        ID3D10Device_VSSetShader(device, vs);
+        ID3D10Device_PSSetShader(device, ps);
+
+        ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, black);
+
+        ID3D10Device_Draw(device, primitives, 0);
+
+        /* Map the last quad while draw is in progress */
+        hr = ID3D10Buffer_Map(vb, dynamic_tests[i].flags, 0, (void **)&quads);
+        todo_wine_if (staging_tests[i].todo)
+            ok(hr == staging_tests[i].hr, "Got unexpected hr %#x. Flags = %s.\n",
+                     hr, staging_tests[i].flags_s);
+        if (SUCCEEDED(hr) && SUCCEEDED(staging_tests[i].hr))
+        {
+            quads[(size / sizeof(quad1)) - 1] = quad2;
+            ID3D10Buffer_Unmap(vb);
+
+            color = get_texture_color(test_context.backbuffer, 160, 360);
+            unsyncronized = compare_color(color, 0xffffff00, 1);
+
+            todo_wine_if (staging_tests[i].todo)
+            {
+                ok((staging_tests[i].unsyncronized == unsyncronized) ||
+                        broken(staging_tests[i].broken),
+                        "Expected buffer mapped %s. Flags = %s. \n",
+                        staging_tests[i].unsyncronized ? "unsyncronized" : "syncronized",
+                        staging_tests[i].flags_s);
+            }
+        }
+        else if (SUCCEEDED(hr))
+        {
+            ID3D10Buffer_Unmap(vb);
+        }
+        ID3D10Buffer_Release(vb);
+    }
+
+    buffer_desc.Usage = D3D10_USAGE_DYNAMIC;
+    buffer_desc.BindFlags = D3D10_BIND_VERTEX_BUFFER;
+    buffer_desc.CPUAccessFlags = D3D10_CPU_ACCESS_WRITE;
+
+    for(i = 0; i < sizeof(dynamic_tests)/sizeof(dynamic_tests[0]); i++)
+    {
+        hr = ID3D10Device_CreateBuffer(device, &buffer_desc, &resource_data, &vb);
+        ok(SUCCEEDED(hr), "Failed to create vertexbuffer.\n");
+
+        ID3D10Device_IASetInputLayout(device, input_layout);
+        ID3D10Device_IASetPrimitiveTopology(device, D3D10_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP);
+        ID3D10Device_IASetVertexBuffers(device, 0, 1, &vb, &stride, &offset);
+        ID3D10Device_VSSetShader(device, vs);
+        ID3D10Device_PSSetShader(device, ps);
+
+        ID3D10Device_ClearRenderTargetView(device, test_context.backbuffer_rtv, black);
+
+        ID3D10Device_Draw(device, primitives, 0);
+
+        /* Map the last quad while draw is in progress */
+        hr = ID3D10Buffer_Map(vb, dynamic_tests[i].flags, 0, (void **)&quads);
+        todo_wine_if (dynamic_tests[i].todo)
+            ok(hr == dynamic_tests[i].hr, "Got unexpected hr %#x. Flags = %s.\n",
+                     hr, dynamic_tests[i].flags_s);
+        if (SUCCEEDED(hr) && SUCCEEDED(dynamic_tests[i].hr))
+        {
+            quads[(size / sizeof(quad1)) - 1] = quad2;
+            ID3D10Buffer_Unmap(vb);
+
+            color = get_texture_color(test_context.backbuffer, 160, 360);
+            unsyncronized = compare_color(color, 0xffffff00, 1);
+
+            todo_wine_if (dynamic_tests[i].todo)
+            {
+                ok((dynamic_tests[i].unsyncronized == unsyncronized) ||
+                        broken(dynamic_tests[i].broken),
+                        "Expected buffer mapped %s. Flags = %s. \n",
+                        dynamic_tests[i].unsyncronized ? "unsyncronized" : "syncronized",
+                        dynamic_tests[i].flags_s);
+            }
+        }
+        else if (SUCCEEDED(hr))
+        {
+            ID3D10Buffer_Unmap(vb);
+        }
+        ID3D10Buffer_Release(vb);
+    }
+
+    ID3D10PixelShader_Release(ps);
+    ID3D10VertexShader_Release(vs);
+    ID3D10InputLayout_Release(input_layout);
+    release_test_context(&test_context);
+    HeapFree(GetProcessHeap(), 0, (void *)resource_data.pSysMem);
+}
+
 START_TEST(device)
 {
     test_feature_level();
@@ -8900,4 +9209,5 @@ START_TEST(device)
     test_immediate_constant_buffer();
     test_fp_specials();
     test_uint_shader_instructions();
+    test_vb_lock_flags();
 }
-- 
2.7.4




More information about the wine-patches mailing list