[PATCH] wined3d: Don't discard buffer data if buffer is not bound.

Paul Gofman pgofman at codeweavers.com
Wed Jul 8 15:44:36 CDT 2020


Fixes geometry flickering on some objects in AION.

Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
 dlls/d3d9/tests/visual.c | 162 +++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/buffer.c    |   3 +
 2 files changed, 165 insertions(+)

diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 38d2875a266..a87f7003807 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -27171,6 +27171,167 @@ static void test_alpha_to_coverage(void)
     DestroyWindow(window);
 }
 
+static void test_buffer_discard(void)
+{
+    unsigned int i, tri_count, size, quad_count;
+    IDirect3DVertexBuffer9 *buffer, *buffer2;
+    D3DADAPTER_IDENTIFIER9 identifier;
+    IDirect3DDevice9 *device;
+    IDirect3D9 *d3d;
+    ULONG refcount;
+    HWND window;
+    HRESULT hr;
+
+    static const struct quad
+    {
+        struct
+        {
+            struct vec3 position;
+            DWORD diffuse;
+        } strip[4];
+    }
+    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;
+
+    window = create_window();
+    ok(!!window, "Failed to create a window.\n");
+
+    d3d = Direct3DCreate9(D3D_SDK_VERSION);
+    ok(!!d3d, "Failed to create a D3D object.\n");
+    if (!(device = create_device(d3d, window, window, TRUE)))
+    {
+        skip("Failed to create a D3D device, skipping tests.\n");
+        IDirect3D9_Release(d3d);
+        DestroyWindow(window);
+        return;
+    }
+
+    hr = IDirect3D9_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    if (adapter_is_warp(&identifier))
+    {
+        skip("Running on WARP, skipping test.\n");
+        goto done;
+    }
+
+    tri_count = 0x100;
+    size = (tri_count + 2) * sizeof(*quad1.strip);
+    quad_count = size / sizeof(quad1);
+
+    hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
+            D3DUSAGE_DYNAMIC, 0, D3DPOOL_DEFAULT, &buffer, NULL);
+    hr = IDirect3DDevice9_CreateVertexBuffer(device, size,
+            D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer2, NULL);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DVertexBuffer9_Lock(buffer, 0, size, (void **)&quads, D3DLOCK_DISCARD);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    for (i = 0; i < quad_count; ++i)
+        quads[i] = quad1;
+
+    hr = IDirect3DVertexBuffer9_Unlock(buffer);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(*quads->strip));
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_BeginScene(device);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri_count);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_EndScene(device);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DVertexBuffer9_Lock(buffer, (quad_count - 1) * sizeof(quad2),
+            sizeof(quad2), (void **)&quads, D3DLOCK_DISCARD);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    *quads = quad2;
+    hr = IDirect3DVertexBuffer9_Unlock(buffer);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DVertexBuffer9_Lock(buffer, 0, size, (void **)&quads, 0);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    /* The data has been reset for the whole buffer. */
+    for (i = 0; i < quad_count - 1; ++i)
+        ok(memcmp(&quads[i], &quad1, sizeof(quad1)), "Quads match, i %u.\n", i);
+
+    ok(!memcmp(&quads[i], &quad2, sizeof(quad2)), "Quads do not match, i %u.\n", i);
+
+    for (i = 0; i < quad_count; ++i)
+        quads[i] = quad1;
+
+    hr = IDirect3DVertexBuffer9_Unlock(buffer);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer2, 0, sizeof(*quads->strip));
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_BeginScene(device);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri_count);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    hr = IDirect3DDevice9_EndScene(device);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DVertexBuffer9_Lock(buffer, (quad_count - 1) * sizeof(quad2),
+            sizeof(quad2), (void **)&quads, D3DLOCK_DISCARD);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+    *quads = quad2;
+    hr = IDirect3DVertexBuffer9_Unlock(buffer);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DVertexBuffer9_Lock(buffer, 0, size, (void **)&quads, 0);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    /* The data are preserved when mapping with MAP_DISCARD on unbound buffer. */
+    for (i = 0; i < quad_count - 1; ++i)
+        ok(!memcmp(&quads[i], &quad1, sizeof(quad1)), "Quads do not match, i %u.\n", i);
+
+    ok(!memcmp(&quads[i], &quad2, sizeof(quad2)), "Quads do not match, i %u.\n", i);
+
+    hr = IDirect3DVertexBuffer9_Unlock(buffer);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+    ok(hr == D3D_OK, "Got unexpected hr %#x.\n", hr);
+
+    IDirect3DVertexBuffer9_Release(buffer);
+    IDirect3DVertexBuffer9_Release(buffer2);
+
+done:
+    refcount = IDirect3DDevice9_Release(device);
+    ok(!refcount, "Device has %u references left.\n", refcount);
+    IDirect3D9_Release(d3d);
+    DestroyWindow(window);
+}
+
 START_TEST(visual)
 {
     D3DADAPTER_IDENTIFIER9 identifier;
@@ -27319,4 +27480,5 @@ START_TEST(visual)
     test_draw_mapped_buffer();
     test_sample_attached_rendertarget();
     test_alpha_to_coverage();
+    test_buffer_discard();
 }
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index b32d0160cc1..9d803efe758 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1049,6 +1049,9 @@ static HRESULT buffer_resource_sub_resource_map(struct wined3d_resource *resourc
         {
             context = context_acquire(device, NULL, 0);
 
+            if (!buffer->resource.bind_count)
+                flags &= ~WINED3D_MAP_DISCARD;
+
             if (flags & WINED3D_MAP_DISCARD)
                 wined3d_buffer_validate_location(buffer, WINED3D_LOCATION_BUFFER);
             else
-- 
2.26.2




More information about the wine-devel mailing list