From: Zebediah Figura zfigura@codeweavers.com
--- dlls/d3d9/tests/visual.c | 59 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 53 insertions(+), 6 deletions(-)
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index bb8381cde3d..1b990301cac 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -27360,14 +27360,9 @@ static void test_dynamic_map_synchronization(void) }
hr = IDirect3DDevice9_CreateVertexBuffer(device, 200 * 4 * sizeof(struct dynamic_vb_vertex), - D3DUSAGE_DYNAMIC, D3DFVF_XYZ, D3DPOOL_DEFAULT, &buffer, NULL); + D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_DEFAULT, &buffer, NULL); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
- hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0); - ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr); - - hr = IDirect3DDevice9_BeginScene(device); - ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(struct dynamic_vb_vertex)); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); @@ -27377,6 +27372,12 @@ static void test_dynamic_map_synchronization(void) hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
+ hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0); + ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + for (y = 0; y < 200; ++y) { hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, D3DLOCK_DISCARD); @@ -27414,6 +27415,52 @@ static void test_dynamic_map_synchronization(void) hr = IDirect3DDevice9_EndScene(device); ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
+ IDirect3DVertexBuffer9_Release(buffer); + + /* Castlevania: Lords of Shadow 2 locks a vertex and index buffer and keeps + * both mapped for all of the draws in a frame. Test this by doing the same + * draws, but with the buffer mapped the whole time. */ + + hr = IDirect3DDevice9_CreateVertexBuffer(device, 200 * 4 * sizeof(struct dynamic_vb_vertex), + D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, D3DFVF_XYZ, D3DPOOL_DEFAULT, &buffer, NULL); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDirect3DDevice9_SetStreamSource(device, 0, buffer, 0, sizeof(struct dynamic_vb_vertex)); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff0000, 0.0f, 0); + ok(hr == D3D_OK, "Failed to clear, hr %#lx.\n", hr); + + hr = IDirect3DDevice9_BeginScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + for (y = 0; y < 200; ++y) + { + hr = IDirect3DVertexBuffer9_Lock(buffer, 0, 0, &data, D3DLOCK_DISCARD); + ok(hr == D3D_OK, "Failed to map buffer, hr %#lx.\n", hr); + + fill_dynamic_vb_quad(data, 0, y); + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 0, 2); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + for (x = 1; x < 200; ++x) + { + fill_dynamic_vb_quad((struct dynamic_vb_vertex *)data + 4 * x, x, y); + hr = IDirect3DDevice9_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, 4 * x, 2); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + } + + hr = IDirect3DVertexBuffer9_Unlock(buffer); + ok(hr == D3D_OK, "Failed to map buffer, hr %#lx.\n", hr); + } + + hr = IDirect3DDevice9_EndScene(device); + ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr); + + hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt); + ok(hr == S_OK, "Failed to get render target, hr %#lx.\n", hr); + check_rt_color_todo(rt, 0x0000ff00); + IDirect3DSurface9_Release(rt); + IDirect3DVertexBuffer9_Release(buffer); refcount = IDirect3DDevice9_Release(device); ok(!refcount, "Device has %lu references left.\n", refcount);
From: Zebediah Figura zfigura@codeweavers.com
https://bugs.winehq.org/show_bug.cgi?id=55591 --- dlls/d3d9/device.c | 14 ++++++++++++++ dlls/d3d9/tests/visual.c | 12 +++--------- dlls/wined3d/cs.c | 28 ++++++++++++++++++++++++++++ dlls/wined3d/wined3d.spec | 1 + include/wine/wined3d.h | 2 ++ 5 files changed, 48 insertions(+), 9 deletions(-)
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 1eeefac6cc0..1267dc8fca1 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -3120,6 +3120,17 @@ static HRESULT d3d9_device_upload_sysmem_index_buffer(struct d3d9_device *device return S_OK; }
+static void d3d9_device_flush_mapped_vertex_buffers(struct d3d9_device *device) +{ + for (unsigned int i = 0; i < WINED3D_MAX_STREAMS; ++i) + { + struct wined3d_buffer *buffer = device->stateblock_state->streams[i].buffer; + + if (buffer) + wined3d_device_context_flush_mapped_buffer(device->immediate_context, buffer); + } +} + static void d3d9_device_upload_managed_textures(struct d3d9_device *device) { const struct wined3d_stateblock_state *state = device->stateblock_state; @@ -3159,6 +3170,7 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, 0, start_vertex, vertex_count); + d3d9_device_flush_mapped_vertex_buffers(device); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); @@ -3200,11 +3212,13 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface index_count = vertex_count_from_primitive_count(primitive_type, primitive_count); d3d9_device_upload_managed_textures(device); d3d9_device_upload_sysmem_vertex_buffers(device, base_vertex_idx, min_vertex_idx, vertex_count); + d3d9_device_flush_mapped_vertex_buffers(device); d3d9_generate_auto_mipmaps(device); wined3d_device_context_set_primitive_type(device->immediate_context, wined3d_primitive_type_from_d3d(primitive_type), 0); wined3d_device_apply_stateblock(device->wined3d_device, device->state); d3d9_device_upload_sysmem_index_buffer(device, &start_idx, index_count); + wined3d_device_context_flush_mapped_buffer(device->immediate_context, device->stateblock_state->index_buffer); wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_idx, start_idx, index_count, 0, device->stateblock_state->streams[0].frequency); d3d9_rts_flag_auto_gen_mipmap(device); diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index 1b990301cac..2d54920ddba 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -26720,7 +26720,6 @@ static void test_draw_mapped_buffer(void) unsigned int color, i; IDirect3D9 *d3d; ULONG refcount; - BOOL test_pass; HWND window; HRESULT hr; void *data; @@ -26741,11 +26740,10 @@ static void test_draw_mapped_buffer(void) { D3DPOOL pool; DWORD usage; - BOOL ignore_wine_result; } tests[] = { - {D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC, TRUE}, + {D3DPOOL_DEFAULT, D3DUSAGE_DYNAMIC}, {D3DPOOL_MANAGED, 0}, {D3DPOOL_SYSTEMMEM, 0}, }; @@ -26825,11 +26823,7 @@ static void test_draw_mapped_buffer(void) ok(hr == D3D_OK, "Got unexpected hr %#lx.\n", hr);
color = getPixelColor(device, 160, 120); - - test_pass = color_match(color, 0x00ff0000, 1); - todo_wine_if(tests[i].ignore_wine_result && !test_pass) - ok(test_pass, "Got unexpected color 0x%08x, test %u.\n", color, i); - + ok(color_match(color, 0x00ff0000, 1), "Got unexpected color 0x%08x, test %u.\n", color, i); color = getPixelColor(device, 480, 360); ok(color_match(color, 0x000000ff, 1), "Got unexpected color 0x%08x, test %u.\n", color, i);
@@ -27458,7 +27452,7 @@ static void test_dynamic_map_synchronization(void)
hr = IDirect3DDevice9_GetRenderTarget(device, 0, &rt); ok(hr == S_OK, "Failed to get render target, hr %#lx.\n", hr); - check_rt_color_todo(rt, 0x0000ff00); + check_rt_color(rt, 0x0000ff00); IDirect3DSurface9_Release(rt);
IDirect3DVertexBuffer9_Release(buffer); diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 7c6e465844c..bf171326926 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -3459,6 +3459,34 @@ static DWORD WINAPI wined3d_cs_run(void *ctx) FreeLibraryAndExitThread(wined3d_module, 0); }
+void CDECL wined3d_device_context_flush_mapped_buffer(struct wined3d_device_context *context, + struct wined3d_buffer *buffer) +{ + struct wined3d_client_resource *client = &buffer->resource.client; + + /* d3d9 applications can draw from a mapped dynamic buffer. + * Castlevania 2 depends on this behaviour. + * This means that we need to upload a pending discard bo, without actually + * unmapping it. */ + + assert(context == &context->device->cs->c); + + if (wined3d_bo_address_is_null(&client->mapped_upload.addr)) + return; + + if (client->mapped_upload.flags & UPLOAD_BO_UPLOAD_ON_UNMAP) + wined3d_device_context_upload_bo(context, &buffer->resource, 0, + &client->mapped_box, &client->mapped_upload, buffer->resource.size, buffer->resource.size); + + if (client->mapped_upload.flags & UPLOAD_BO_RENAME_ON_UNMAP) + { + client->mapped_upload.flags &= ~UPLOAD_BO_RENAME_ON_UNMAP; + /* This logic matches wined3d_cs_map_upload_bo(). */ + if (client->mapped_upload.addr.buffer_object->coherent && wined3d_map_persistent()) + client->mapped_upload.flags &= ~UPLOAD_BO_UPLOAD_ON_UNMAP; + } +} + struct wined3d_cs *wined3d_cs_create(struct wined3d_device *device, const enum wined3d_feature_level *levels, unsigned int level_count) { diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 72e0e3fd8fa..accb6f65658 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -103,6 +103,7 @@ @ cdecl wined3d_device_context_draw_indirect(ptr ptr long long) @ cdecl wined3d_device_context_execute_command_list(ptr ptr long) @ cdecl wined3d_device_context_flush(ptr) +@ cdecl wined3d_device_context_flush_mapped_buffer(ptr ptr) @ cdecl wined3d_device_context_generate_mipmaps(ptr ptr) @ cdecl wined3d_device_context_get_blend_state(ptr ptr ptr) @ cdecl wined3d_device_context_get_constant_buffer(ptr long long ptr) diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index d7a3dd1e0fe..fcbe094e30b 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2458,6 +2458,8 @@ void __cdecl wined3d_device_context_draw_indirect(struct wined3d_device_context void __cdecl wined3d_device_context_execute_command_list(struct wined3d_device_context *context, struct wined3d_command_list *list, bool restore_state); void __cdecl wined3d_device_context_flush(struct wined3d_device_context *context); +void __cdecl wined3d_device_context_flush_mapped_buffer(struct wined3d_device_context *context, + struct wined3d_buffer *buffer); void __cdecl wined3d_device_context_generate_mipmaps(struct wined3d_device_context *context, struct wined3d_shader_resource_view *view); struct wined3d_blend_state * __cdecl wined3d_device_context_get_blend_state(