Commit 7b4e88e0 authored by Henri Verbeet's avatar Henri Verbeet Committed by Alexandre Julliard

d3d8/tests: Introduce a test for vertex buffer map synchronisation.

Based on a patch by Patrick Rudolph from a while ago. Thanks to Stefan Dösinger for making this test work with AMD drivers. Signed-off-by: 's avatarHenri Verbeet <hverbeet@codeweavers.com> Signed-off-by: 's avatarAlexandre Julliard <julliard@winehq.org>
parent 5aefc4e3
......@@ -9915,6 +9915,223 @@ static void test_drawindexedprimitiveup(void)
DestroyWindow(window);
}
static void test_map_synchronisation(void)
{
LARGE_INTEGER frequency, diff, ts[3];
unsigned int i, j, tri_count, size;
D3DADAPTER_IDENTIFIER8 identifier;
IDirect3DVertexBuffer8 *buffer;
IDirect3DDevice8 *device;
BOOL unsynchronised, ret;
IDirect3D8 *d3d;
D3DCOLOR colour;
ULONG refcount;
D3DCAPS8 caps;
HWND window;
HRESULT hr;
static const struct
{
unsigned int flags;
BOOL unsynchronised;
}
tests[] =
{
{0, FALSE},
{D3DLOCK_NOOVERWRITE, TRUE},
{D3DLOCK_DISCARD, FALSE},
{D3DLOCK_NOOVERWRITE | D3DLOCK_DISCARD, TRUE},
};
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 = Direct3DCreate8(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");
IDirect3D8_Release(d3d);
DestroyWindow(window);
return;
}
hr = IDirect3D8_GetAdapterIdentifier(d3d, D3DADAPTER_DEFAULT, 0, &identifier);
ok(SUCCEEDED(hr), "Failed to get adapter identifier, hr %#x.\n", hr);
/* Maps are always synchronised on WARP. */
if (adapter_is_warp(&identifier))
{
skip("Running on WARP, skipping test.\n");
goto done;
}
hr = IDirect3DDevice8_GetDeviceCaps(device, &caps);
ok(SUCCEEDED(hr), "Failed to get device caps, hr %#x.\n", hr);
tri_count = 0x1000;
if (tri_count > caps.MaxPrimitiveCount)
{
skip("Device supports only %u primitives, skipping test.\n", caps.MaxPrimitiveCount);
goto done;
}
size = (tri_count + 2) * sizeof(*quad1.strip);
ret = QueryPerformanceFrequency(&frequency);
ok(ret, "Failed to get performance counter frequency.\n");
hr = IDirect3DDevice8_CreateVertexBuffer(device, size,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
hr = IDirect3DVertexBuffer8_Lock(buffer, 0, size, (BYTE **)&quads, D3DLOCK_DISCARD);
ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
for (j = 0; j < size / sizeof(*quads); ++j)
{
quads[j] = quad1;
}
hr = IDirect3DVertexBuffer8_Unlock(buffer);
ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr);
hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE);
ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quads->strip));
ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
/* Initial draw to initialise states, compile shaders, etc. */
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice8_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri_count);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice8_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
/* Read the result to ensure the GPU has finished drawing. */
colour = getPixelColor(device, 320, 240);
/* Time drawing tri_count triangles. */
ret = QueryPerformanceCounter(&ts[0]);
ok(ret, "Failed to read performance counter.\n");
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice8_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri_count);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice8_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
colour = getPixelColor(device, 320, 240);
/* Time drawing a single triangle. */
ret = QueryPerformanceCounter(&ts[1]);
ok(ret, "Failed to read performance counter.\n");
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice8_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 1);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice8_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
colour = getPixelColor(device, 320, 240);
ret = QueryPerformanceCounter(&ts[2]);
ok(ret, "Failed to read performance counter.\n");
IDirect3DVertexBuffer8_Release(buffer);
/* Estimate the number of triangles we can draw in 100ms. */
diff.QuadPart = ts[1].QuadPart - ts[0].QuadPart + ts[1].QuadPart - ts[2].QuadPart;
tri_count = (tri_count * frequency.QuadPart) / (diff.QuadPart * 10);
tri_count = ((tri_count + 2 + 3) & ~3) - 2;
if (tri_count > caps.MaxPrimitiveCount)
{
skip("Would need to draw %u triangles, but the device only supports %u primitives.\n",
tri_count, caps.MaxPrimitiveCount);
goto done;
}
size = (tri_count + 2) * sizeof(*quad1.strip);
for (i = 0; i < sizeof(tests) / sizeof(*tests); ++i)
{
hr = IDirect3DDevice8_CreateVertexBuffer(device, size,
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &buffer);
ok(SUCCEEDED(hr), "Failed to create vertex buffer, hr %#x.\n", hr);
hr = IDirect3DVertexBuffer8_Lock(buffer, 0, size, (BYTE **)&quads, D3DLOCK_DISCARD);
ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
for (j = 0; j < size / sizeof(*quads); ++j)
{
quads[j] = quad1;
}
hr = IDirect3DVertexBuffer8_Unlock(buffer);
ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
hr = IDirect3DDevice8_SetStreamSource(device, 0, buffer, sizeof(*quads->strip));
ok(SUCCEEDED(hr), "Failed to set stream source, hr %#x.\n", hr);
/* Start a draw operation. */
hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff0000ff, 0.0f, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice8_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice8_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, tri_count);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice8_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
/* Map the last quad while the draw is in progress. */
hr = IDirect3DVertexBuffer8_Lock(buffer, size - sizeof(quad2),
sizeof(quad2), (BYTE **)&quads, tests[i].flags);
ok(SUCCEEDED(hr), "Failed to lock vertex buffer, hr %#x.\n", hr);
*quads = quad2;
hr = IDirect3DVertexBuffer8_Unlock(buffer);
ok(SUCCEEDED(hr), "Failed to unlock vertex buffer, hr %#x.\n", hr);
colour = getPixelColor(device, 320, 240);
unsynchronised = color_match(colour, D3DCOLOR_ARGB(0x00, 0xff, 0xff, 0x00), 1);
ok(tests[i].unsynchronised == unsynchronised, "Expected %s map for flags %#x.\n",
tests[i].unsynchronised ? "unsynchronised" : "synchronised", tests[i].flags);
hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr);
IDirect3DVertexBuffer8_Release(buffer);
}
done:
refcount = IDirect3DDevice8_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D8_Release(d3d);
DestroyWindow(window);
}
START_TEST(visual)
{
D3DADAPTER_IDENTIFIER8 identifier;
......@@ -9986,4 +10203,5 @@ START_TEST(visual)
test_max_index16();
test_backbuffer_resize();
test_drawindexedprimitiveup();
test_map_synchronisation();
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment