Fixes geometry flickering on some objects in AION.
Signed-off-by: Paul Gofman pgofman@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