[PATCH 4/6] ddraw/tests: Add visual tests for locking vertexbuffers

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


Test flags DDLOCK_NOOVERWRITE and DDLOCK_DISCARDCONTENTS on
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 results were the same on the following systems:
* Nvidia ION on Windows 7
* AMD Radeon Mobility HD4300 Series on Windows 7
* Nvidia Quadro NVS 140M on Windows 8

Tests showed that given both DDLOCK_NOOVERWRITE and DDLOCK_DISCARDCONTENTS
the buffer is mapped unsyncronized.

The flag DDLOCK_NOOVERWRITE has only effect on buffers created with
dwCaps D3DVBCAPS_WRITEONLY.

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

diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c
index 4f62133..8a510ff 100644
--- a/dlls/ddraw/tests/visual.c
+++ b/dlls/ddraw/tests/visual.c
@@ -1519,6 +1519,181 @@ static void depth_clamp_test(IDirect3DDevice7 *device)
     ok(SUCCEEDED(hr), "SetViewport failed, hr %#x.\n", hr);
 }
 
+static void test_vb_lock_flags(IDirect3DDevice7 *device)
+{
+    IDirect3DVertexBuffer7 *buffer;
+    ULONG timestamp1, timestamp2;
+    D3DVERTEXBUFFERDESC vb_desc;
+    DWORD i, j, tri, size;
+    BOOL unsyncronized;
+    IDirect3D7 *d3d7;
+    D3DCOLOR color;
+    HRESULT hr;
+
+    static const struct
+    {
+        const char *flags_s;
+        unsigned int flags;
+        DWORD dwCaps;
+        BOOL unsyncronized;
+        BOOL todo;
+        BOOL broken;
+    }
+    tests[] =
+    {
+        {"0", 0, 0, FALSE, FALSE, FALSE},
+        {"0", 0, D3DVBCAPS_WRITEONLY, FALSE, FALSE, FALSE},
+        {"DDLOCK_NOOVERWRITE", DDLOCK_NOOVERWRITE, 0, FALSE, FALSE, FALSE},
+        {"DDLOCK_NOOVERWRITE", DDLOCK_NOOVERWRITE, D3DVBCAPS_WRITEONLY, TRUE, TRUE, FALSE},
+        {"DDLOCK_DISCARDCONTENTS", DDLOCK_DISCARDCONTENTS, 0, FALSE, FALSE, FALSE},
+        {"DDLOCK_DISCARDCONTENTS", DDLOCK_DISCARDCONTENTS, D3DVBCAPS_WRITEONLY, FALSE, FALSE, FALSE},
+        {"DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS",
+                DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, 0, FALSE, FALSE, FALSE},
+        {"DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS",
+                DDLOCK_NOOVERWRITE | DDLOCK_DISCARDCONTENTS, D3DVBCAPS_WRITEONLY, TRUE, TRUE, FALSE},
+        {"DDLOCK_NOOVERWRITE | DDLOCK_READONLY",
+                DDLOCK_NOOVERWRITE | DDLOCK_READONLY, 0, FALSE, FALSE, FALSE},
+        {"DDLOCK_NOOVERWRITE | DDLOCK_READONLY",
+                DDLOCK_NOOVERWRITE | DDLOCK_READONLY, D3DVBCAPS_WRITEONLY, TRUE, TRUE, FALSE},
+    };
+
+    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;
+
+    size = 0x1000;
+    /* calculate triangle count */
+    tri = (size / sizeof(quad1)) * 4;
+
+    hr = IDirect3DDevice7_GetDirect3D(device, &d3d7);
+    ok(SUCCEEDED(hr), "Failed to get Direct3D7 interface, hr %#x.\n", hr);
+
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+    ok(SUCCEEDED(hr), "Failed to disable lighting, hr %#x.\n", hr);
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
+    ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
+
+    memset(&vb_desc, 0, sizeof(vb_desc));
+    vb_desc.dwSize = sizeof(vb_desc);
+    vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+    vb_desc.dwNumVertices = tri;
+    /* calibrate vertexbuffer size to allow the test to pass on slow and fast systems */
+    hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &buffer, 0);
+    ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
+
+    hr = IDirect3DVertexBuffer7_Lock(buffer, 0, (void **)&quads, NULL);
+    ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
+
+    /* place quads */
+    for (j = 0; j < size / sizeof(quad1); j++)
+        quads[j] = quad1;
+
+    hr = IDirect3DVertexBuffer7_Unlock(buffer);
+    ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
+
+    timestamp1 = GetTickCount();
+
+    /* draw a quad to make use of the bound buffer */
+    hr = IDirect3DDevice7_BeginScene(device);
+    ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+    hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, tri, 0);
+    ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+    hr = IDirect3DDevice7_EndScene(device);
+    ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+    /* dummy read to wait for GPU being done */
+    color = getPixelColor(device, 160, 360);
+
+    timestamp2 = GetTickCount();
+
+    IDirect3DVertexBuffer7_Release(buffer);
+
+    /* Adjust buffer size for 1 second draw call duration */
+    size = (size * 1000UL) / (timestamp2 - timestamp1 + 1);
+
+    /* calculate triangle count */
+    tri = (size / sizeof(quad1)) * 4;
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i)
+    {
+        memset(&vb_desc, 0, sizeof(vb_desc));
+        vb_desc.dwSize = sizeof(vb_desc);
+        vb_desc.dwCaps = tests[i].dwCaps;
+        vb_desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE;
+        vb_desc.dwNumVertices = tri;
+        hr = IDirect3D7_CreateVertexBuffer(d3d7, &vb_desc, &buffer, 0);
+        ok(SUCCEEDED(hr), "Failed to create source vertex buffer, hr %#x.\n", hr);
+
+        hr = IDirect3DVertexBuffer7_Lock(buffer, 0, (void **)&quads, NULL);
+        ok(SUCCEEDED(hr), "Failed to lock source vertex buffer, hr %#x.\n", hr);
+
+        /* place quads */
+        for (j = 0; j < size / sizeof(quad1); j++)
+            quads[j] = quad1;
+
+        hr = IDirect3DVertexBuffer7_Unlock(buffer);
+        ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
+
+        hr = IDirect3DDevice7_Clear(Direct3DDevice, 0, NULL, D3DCLEAR_TARGET, 0x00000000, 0.0, 0);
+        ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
+
+        /* draw a quad to make use of the bound buffer */
+        hr = IDirect3DDevice7_BeginScene(device);
+        ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+        hr = IDirect3DDevice7_DrawPrimitiveVB(device, D3DPT_TRIANGLESTRIP, buffer, 0, tri, 0);
+        ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+        hr = IDirect3DDevice7_EndScene(device);
+        ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+        /* Map the last quad while draw is in progress */
+        hr = IDirect3DVertexBuffer7_Lock(buffer, tests[i].flags, (void **)&quads, NULL);
+        ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
+
+        /* Replace last quad with yellow quad */
+        quads[(size / sizeof(quad1)) - 1] = quad2;
+
+        hr = IDirect3DVertexBuffer7_Unlock(buffer);
+        ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
+
+        /* Test if last triangle has different color */
+        color = getPixelColor(device, 160, 360);
+        unsyncronized = color_match(color, 0x00ffff00, 1);
+        IDirect3DVertexBuffer7_Release(buffer);
+
+        todo_wine_if (tests[i].todo)
+        {
+            ok((tests[i].unsyncronized == unsyncronized) || broken(tests[i].broken),
+                    "Expected buffer mapped %s. Flags = %s. dwCaps = %#x.\n",
+                    tests[i].unsyncronized ? "unsyncronized" : "syncronized",
+                    tests[i].flags_s, tests[i].dwCaps);
+        }
+    }
+    IDirect3D7_Release(d3d7);
+}
+
 static void DX1_BackBufferFlipTest(void)
 {
     HRESULT hr;
@@ -1687,6 +1862,7 @@ START_TEST(visual)
     test_blend(Direct3DDevice);
     rhw_zero_test(Direct3DDevice);
     cubemap_test(Direct3DDevice);
+    test_vb_lock_flags(Direct3DDevice);
 
     releaseObjects(); /* release DX7 interfaces to test D3D1 */
 
-- 
2.7.4




More information about the wine-patches mailing list