[PATCH 1/3] d3d9/tests/visual: Add Vertexbuffer locking tests, try 2

Patrick Rudolph siro at das-labor.org
Mon Jul 11 11:13:01 CDT 2016


Test flags D3DLOCK_NOOVERWRITE and D3DLOCK_DISCARD on POOL_DEFAULT
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
(and primitive count) is incremented a few times.

The results have been verified on Windows 7 and
AMD Radeon Mobility HD4300 Series.

Given D3DLOCK_NOOVERWRITE the flag D3DLOCK_DISCARD has no effect.
The flag D3DLOCK_NOOVERWRITE works on both DYNAMIC and non-DYNAMIC
buffers.

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

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index a2adc54..6f59b43 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -4309,6 +4309,234 @@ done:
     DestroyWindow(window);
 }
 
+static void test_vb_lock_flags(void)
+{
+    IDirect3DVertexBuffer9 *buffer;
+    IDirect3DDevice9 *device;
+    IDirect3D9 *d3d9;
+    DWORD i, j, tri, quads;
+    HWND window;
+    HRESULT hr;
+    ULONG size;
+    unsigned refcount;
+    D3DCOLOR color;
+    BOOL unsyncronized;
+    D3DCAPS9 caps;
+
+    static const struct
+    {
+        const char *flags_s;
+        unsigned int flags;
+        BOOL usage;
+        BOOL unsyncronized;
+        BOOL todo;
+    }
+    tests[] =
+    {
+        {
+            "0",
+            0,
+            0,
+            FALSE,
+            FALSE
+        },
+        {
+            "0",
+            0,
+            D3DUSAGE_DYNAMIC,
+            FALSE,
+            FALSE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE",
+            D3DLOCK_NOOVERWRITE,
+            0,
+            TRUE,
+            TRUE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE",
+            D3DLOCK_NOOVERWRITE,
+            D3DUSAGE_DYNAMIC,
+            TRUE,
+            FALSE
+        },
+        {
+            "D3DLOCK_DISCARD",
+            D3DLOCK_DISCARD,
+            0,
+            FALSE,
+            FALSE
+        },
+        {
+            "D3DLOCK_DISCARD",
+            D3DLOCK_DISCARD,
+            D3DUSAGE_DYNAMIC,
+            FALSE,
+            FALSE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",
+            D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,
+            0,
+            TRUE,
+            TRUE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD",
+            D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD,
+            D3DUSAGE_DYNAMIC,
+            TRUE,
+            TRUE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",
+            D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,
+            0,
+            TRUE,
+            TRUE
+        },
+        {
+            "D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY",
+            D3DLOCK_NOOVERWRITE | D3DLOCK_READONLY,
+            D3DUSAGE_DYNAMIC,
+            TRUE,
+            TRUE
+        },
+    };
+
+    static struct
+    {
+        struct
+        {
+            struct vec3 position;
+            DWORD diffuse;
+        } strip[4];
+    }
+    *quad_strip_array, quad_strip1 =
+    {
+        {
+            {{-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},
+        }
+    },
+    quad_strip2 =
+    {
+        {
+            {{-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},
+        }
+    };
+
+    window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE,
+            0, 0, 640, 480, NULL, NULL, NULL, NULL);
+    ok(!!window, "Failed to create a window.\n");
+
+    d3d9 = Direct3DCreate9(D3D_SDK_VERSION);
+    ok(!!d3d9, "Failed to create a D3D object.\n");
+    if (!(device = create_device(d3d9, window, window, TRUE)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D9_Release(d3d9);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3DDevice9_GetDeviceCaps(device, &caps);
+    ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
+    ok(hr == D3D_OK, "IDirect3DDevice9_SetRenderState returned %08x\n", hr);
+
+    hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
+    ok(hr == D3D_OK, "IDirect3DDevice9_SetFVF failed with %08x\n", hr);
+
+    for (i = 0; i < sizeof(tests)/sizeof(tests[0]); ++i)
+    {
+        unsyncronized = FALSE;
+
+        /* Increase triangle draw count for faster GPUs.
+          Limit size to 0x40000 as bigger values causes the Nvidia driver to crash. */
+        for (size = 0x1000; size <= 0x40000; size <<= 1)
+        {
+            /* calculate triangle count */
+            tri = (size / sizeof(quad_strip1.strip[0])) - 2;
+            if (tri > caps.MaxPrimitiveCount)
+                break;
+
+            quads = size / sizeof(quad_strip1);
+
+            hr = IDirect3DDevice9_CreateVertexBuffer(device, size, tests[i].usage, 0, D3DPOOL_DEFAULT, &buffer, NULL);
+            ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
+            if (!SUCCEEDED(hr))
+                continue;
+
+            /* place quads */
+            hr = IDirect3DVertexBuffer9_Lock(buffer, 0, size, (void **)&quad_strip_array, 0);
+            ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
+
+            for (j = 0; j < quads; j++)
+                quad_strip_array[j] = quad_strip1;
+
+            hr = IDirect3DVertexBuffer9_Unlock(buffer);
+            ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
+
+            hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(quad_strip1.strip[0]));
+            ok(hr == D3D_OK, "Failed to set stream source, hr %#x.\n", hr);
+
+            /* draw a quad to make use of the bound buffer */
+            hr = IDirect3DDevice9_BeginScene(device);
+            ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
+            hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri);
+            ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
+            hr = IDirect3DDevice9_EndScene(device);
+            ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
+
+            /* Map the last quad while draw is in progress */
+            hr = IDirect3DVertexBuffer9_Lock(buffer, (quads - 1) * sizeof(quad_strip1),
+                    sizeof(quad_strip1), (void **)&quad_strip_array, tests[i].flags);
+            ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
+
+            /* Replace last quad with yellow quad */
+            quad_strip_array[0] = quad_strip2;
+
+            hr = IDirect3DVertexBuffer9_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, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1);
+
+            IDirect3DVertexBuffer9_Release(buffer);
+
+            hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+            ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
+
+            if (tests[i].unsyncronized == unsyncronized)
+                break;
+        }
+        if (tests[i].todo)
+        {
+            todo_wine ok(tests[i].unsyncronized == unsyncronized, "Expected buffer mapped %s. Flags = %s. Usage = %d.\n",
+                tests[i].unsyncronized ? "unsyncronized" : "syncronized", tests[i].flags_s, tests[i].usage);
+        }
+        else
+        {
+            ok(tests[i].unsyncronized == unsyncronized, "Expected buffer mapped %s. Flags = %s. Usage = %d.\n",
+                tests[i].unsyncronized ? "unsyncronized" : "syncronized", tests[i].flags_s, tests[i].usage);
+        }
+    }
+
+    refcount = IDirect3DDevice9_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirect3D9_Release(d3d9);
+    DestroyWindow(window);
+}
+
 static void release_buffer_test(void)
 {
     IDirect3DVertexBuffer9 *vb;
@@ -21794,4 +22022,5 @@ START_TEST(visual)
     test_multisample_init();
     test_texture_blending();
     test_color_clamping();
+    test_vb_lock_flags();
 }
-- 
2.7.4




More information about the wine-patches mailing list