From: Henri Verbeet hverbeet@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45486 Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3d9/buffer.c | 24 ++++++++++++++-- dlls/d3d9/d3d9_private.h | 4 +++ dlls/d3d9/device.c | 60 ++++++++++++++++++++++++++++++++++++---- dlls/d3d9/stateblock.c | 17 ++++++++++++ 4 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/dlls/d3d9/buffer.c b/dlls/d3d9/buffer.c index 02b3570402f..15b7e2bdbce 100644 --- a/dlls/d3d9/buffer.c +++ b/dlls/d3d9/buffer.c @@ -59,6 +59,8 @@ static ULONG WINAPI d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface) IDirect3DDevice9Ex_AddRef(buffer->parent_device); wined3d_mutex_lock(); wined3d_buffer_incref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_incref(buffer->draw_buffer); wined3d_mutex_unlock(); }
@@ -78,6 +80,8 @@ static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
wined3d_mutex_lock(); wined3d_buffer_decref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_decref(buffer->draw_buffer); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -274,6 +278,7 @@ static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops = HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *device, UINT size, UINT usage, DWORD fvf, D3DPOOL pool) { + const struct wined3d_parent_ops *parent_ops = &d3d9_null_wined3d_parent_ops; struct wined3d_buffer_desc desc; HRESULT hr;
@@ -299,15 +304,28 @@ HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *
desc.byte_width = size; desc.usage = usage & WINED3DUSAGE_MASK; - desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + desc.bind_flags = 0; desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; desc.misc_flags = 0; desc.structure_byte_stride = 0;
+ if (desc.access & WINED3D_RESOURCE_ACCESS_GPU) + { + desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + parent_ops = &d3d9_vertexbuffer_wined3d_parent_ops; + } + wined3d_mutex_lock(); - hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, - &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, parent_ops, &buffer->wined3d_buffer); + if (SUCCEEDED(hr) && !(desc.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, + &d3d9_vertexbuffer_wined3d_parent_ops, &buffer->draw_buffer))) + wined3d_buffer_decref(buffer->wined3d_buffer); + } wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index d6155eba60b..8647aac4af1 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -42,6 +42,7 @@
#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256 #define D3D9_MAX_TEXTURE_UNITS 20 +#define D3D9_MAX_STREAMS 16
#define D3DPRESENTFLAGS_MASK 0x00000fffu
@@ -105,6 +106,8 @@ struct d3d9_device BOOL in_destruction; BOOL in_scene; BOOL has_vertex_declaration; + BOOL recording; + unsigned int upload_map;
unsigned int max_user_clip_planes;
@@ -181,6 +184,7 @@ struct d3d9_vertexbuffer struct d3d9_resource resource; struct wined3d_buffer *wined3d_buffer; IDirect3DDevice9Ex *parent_device; + struct wined3d_buffer *draw_buffer; DWORD fvf; };
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index f19e2ae6f65..7c488bfd601 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -974,6 +974,7 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
if (!extended) { + device->recording = FALSE; wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil); } @@ -2317,7 +2318,8 @@ static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - hr = wined3d_device_begin_stateblock(device->wined3d_device); + if (SUCCEEDED(hr = wined3d_device_begin_stateblock(device->wined3d_device))) + device->recording = TRUE; wined3d_mutex_unlock();
return hr; @@ -2340,6 +2342,7 @@ static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDire WARN("Failed to end the state block, hr %#x.\n", hr); return hr; } + device->recording = FALSE;
if (!(object = heap_alloc_zero(sizeof(*object)))) { @@ -2688,10 +2691,38 @@ static void d3d9_generate_auto_mipmaps(struct d3d9_device *device) } }
+static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device, + unsigned int start_vertex, unsigned int vertex_count) +{ + struct wined3d_box box = {0, 0, 0, 1, 0, 1}; + struct d3d9_vertexbuffer *d3d9_buffer; + unsigned int i, offset, stride, map; + struct wined3d_buffer *dst_buffer; + HRESULT hr; + + map = device->upload_map; + while (map) + { + i = ffs(map) - 1; + map ^= 1u << i; + + if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, i, &dst_buffer, &offset, &stride))) + ERR("Failed to get stream source.\n"); + d3d9_buffer = wined3d_buffer_get_parent(dst_buffer); + box.left = offset + start_vertex * stride; + box.right = box.left + vertex_count * stride; + if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, + wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0, + wined3d_buffer_get_resource(d3d9_buffer->wined3d_buffer), 0, &box, 0))) + ERR("Failed to update buffer.\n"); + } +} + static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); + unsigned int vertex_count; HRESULT hr;
TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", @@ -2704,10 +2735,11 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, WARN("Called without a valid vertex declaration set.\n"); return D3DERR_INVALIDCALL; } + vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); + d3d9_device_upload_sysmem_buffers(device, start_vertex, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); - hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, - vertex_count_from_primitive_count(primitive_type, primitive_count)); + hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count); if (SUCCEEDED(hr)) d3d9_rts_flag_auto_gen_mipmap(device); wined3d_mutex_unlock(); @@ -2734,6 +2766,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface WARN("Called without a valid vertex declaration set.\n"); return D3DERR_INVALIDCALL; } + d3d9_device_upload_sysmem_buffers(device, min_vertex_idx, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); @@ -3378,6 +3411,7 @@ static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer9(buffer); + struct wined3d_buffer *wined3d_buffer; HRESULT hr;
TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n", @@ -3386,14 +3420,28 @@ static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, wined3d_mutex_lock(); if (!stride) { - struct wined3d_buffer *wined3d_buffer; unsigned int cur_offset;
hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, &cur_offset, &stride); } - hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, - buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride); + + if (!buffer_impl) + wined3d_buffer = NULL; + else if (buffer_impl->draw_buffer) + wined3d_buffer = buffer_impl->draw_buffer; + else + wined3d_buffer = buffer_impl->wined3d_buffer; + + hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, wined3d_buffer, offset, stride); + if (SUCCEEDED(hr) && !device->recording) + { + if (buffer_impl && buffer_impl->draw_buffer) + device->upload_map |= (1u << stream_idx); + else + device->upload_map &= ~(1u << stream_idx); + } + wined3d_mutex_unlock();
return hr; diff --git a/dlls/d3d9/stateblock.c b/dlls/d3d9/stateblock.c index 62b3bacb28d..c5306fd80b3 100644 --- a/dlls/d3d9/stateblock.c +++ b/dlls/d3d9/stateblock.c @@ -108,11 +108,28 @@ static HRESULT WINAPI d3d9_stateblock_Capture(IDirect3DStateBlock9 *iface) static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface) { struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface); + struct wined3d_buffer *wined3d_buffer; + struct d3d9_vertexbuffer *buffer; + unsigned int i, offset, stride; + struct d3d9_device *device; + HRESULT hr;
TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); wined3d_stateblock_apply(stateblock->wined3d_stateblock); + device = impl_from_IDirect3DDevice9Ex(stateblock->parent_device); + device->upload_map = 0; + for (i = 0; i < D3D9_MAX_STREAMS; ++i) + { + if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, + i, &wined3d_buffer, &offset, &stride))) + continue; + if (!wined3d_buffer || !(buffer = wined3d_buffer_get_parent(wined3d_buffer))) + continue; + if (buffer->draw_buffer) + device->upload_map |= 1u << i; + } wined3d_mutex_unlock();
return D3D_OK;
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3d9/buffer.c | 24 +++++++++++++++++--- dlls/d3d9/d3d9_private.h | 1 + dlls/d3d9/device.c | 47 +++++++++++++++++++++++++++++++++++++--- dlls/d3d9/stateblock.c | 4 ++++ 4 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/dlls/d3d9/buffer.c b/dlls/d3d9/buffer.c index 15b7e2bdbce..1533a8496d2 100644 --- a/dlls/d3d9/buffer.c +++ b/dlls/d3d9/buffer.c @@ -384,6 +384,8 @@ static ULONG WINAPI d3d9_indexbuffer_AddRef(IDirect3DIndexBuffer9 *iface) IDirect3DDevice9Ex_AddRef(buffer->parent_device); wined3d_mutex_lock(); wined3d_buffer_incref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_incref(buffer->draw_buffer); wined3d_mutex_unlock(); }
@@ -403,6 +405,8 @@ static ULONG WINAPI d3d9_indexbuffer_Release(IDirect3DIndexBuffer9 *iface)
wined3d_mutex_lock(); wined3d_buffer_decref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_decref(buffer->draw_buffer); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -597,6 +601,7 @@ static const struct wined3d_parent_ops d3d9_indexbuffer_wined3d_parent_ops = HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *device, UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) { + const struct wined3d_parent_ops *parent_ops = &d3d9_null_wined3d_parent_ops; struct wined3d_buffer_desc desc; HRESULT hr;
@@ -615,19 +620,32 @@ HRESULT indexbuffer_init(struct d3d9_indexbuffer *buffer, struct d3d9_device *de
desc.byte_width = size; desc.usage = (usage & WINED3DUSAGE_MASK) | WINED3DUSAGE_STATICDECL; - desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + desc.bind_flags = 0; desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; desc.misc_flags = 0; desc.structure_byte_stride = 0;
+ if (desc.access & WINED3D_RESOURCE_ACCESS_GPU) + { + desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + parent_ops = &d3d9_indexbuffer_wined3d_parent_ops; + } + buffer->IDirect3DIndexBuffer9_iface.lpVtbl = &d3d9_indexbuffer_vtbl; buffer->format = wined3dformat_from_d3dformat(format); d3d9_resource_init(&buffer->resource);
wined3d_mutex_lock(); - hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, - &d3d9_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, parent_ops, &buffer->wined3d_buffer); + if (SUCCEEDED(hr) && !(desc.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, + &d3d9_indexbuffer_wined3d_parent_ops, &buffer->draw_buffer))) + wined3d_buffer_decref(buffer->wined3d_buffer); + } wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index 8647aac4af1..6f3c71e2910 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -198,6 +198,7 @@ struct d3d9_indexbuffer struct d3d9_resource resource; struct wined3d_buffer *wined3d_buffer; IDirect3DDevice9Ex *parent_device; + struct wined3d_buffer *draw_buffer; enum wined3d_format_id format; };
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index 7c488bfd601..dcd6100026d 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -2700,7 +2700,7 @@ static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device, struct wined3d_buffer *dst_buffer; HRESULT hr;
- map = device->upload_map; + map = device->upload_map & ((1u << D3D9_MAX_STREAMS) - 1); while (map) { i = ffs(map) - 1; @@ -2718,6 +2718,31 @@ static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device, } }
+static void d3d9_device_upload_sysmem_index_buffer(struct d3d9_device *device, + unsigned int start_idx, unsigned int idx_count) +{ + struct wined3d_box box = {0, 0, 0, 1, 0, 1}; + struct d3d9_vertexbuffer *d3d9_buffer; + struct wined3d_buffer *dst_buffer; + enum wined3d_format_id format; + unsigned int offset, idx_size; + HRESULT hr; + + if (~device->upload_map & (1u << D3D9_MAX_STREAMS)) + return; + + if (!(dst_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &format, &offset))) + ERR("Failed to get index buffer.\n"); + d3d9_buffer = wined3d_buffer_get_parent(dst_buffer); + idx_size = format == WINED3DFMT_R16_UINT ? 2 : 4; + box.left = offset + start_idx * idx_size; + box.right = box.left + idx_count * idx_size; + if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, + wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0, + wined3d_buffer_get_resource(d3d9_buffer->wined3d_buffer), 0, &box, 0))) + ERR("Failed to update buffer.\n"); +} + static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { @@ -2767,6 +2792,8 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface return D3DERR_INVALIDCALL; } d3d9_device_upload_sysmem_buffers(device, min_vertex_idx, vertex_count); + d3d9_device_upload_sysmem_index_buffer(device, start_idx, + vertex_count_from_primitive_count(primitive_type, primitive_count)); d3d9_generate_auto_mipmaps(device); wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); @@ -3512,12 +3539,26 @@ static HRESULT WINAPI d3d9_device_SetIndices(IDirect3DDevice9Ex *iface, IDirect3 { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer9(buffer); + struct wined3d_buffer *wined3d_buffer;
TRACE("iface %p, buffer %p.\n", iface, buffer);
+ if (!ib) + wined3d_buffer = NULL; + else if (ib->draw_buffer) + wined3d_buffer = ib->draw_buffer; + else + wined3d_buffer = ib->wined3d_buffer; + wined3d_mutex_lock(); - wined3d_device_set_index_buffer(device->wined3d_device, - ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); + wined3d_device_set_index_buffer(device->wined3d_device, wined3d_buffer, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); + if (!device->recording) + { + if (ib && ib->draw_buffer) + device->upload_map |= (1u << D3D9_MAX_STREAMS); + else + device->upload_map &= ~(1u << D3D9_MAX_STREAMS); + } wined3d_mutex_unlock();
return D3D_OK; diff --git a/dlls/d3d9/stateblock.c b/dlls/d3d9/stateblock.c index c5306fd80b3..876e66b74c9 100644 --- a/dlls/d3d9/stateblock.c +++ b/dlls/d3d9/stateblock.c @@ -111,6 +111,7 @@ static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface) struct wined3d_buffer *wined3d_buffer; struct d3d9_vertexbuffer *buffer; unsigned int i, offset, stride; + enum wined3d_format_id format; struct d3d9_device *device; HRESULT hr;
@@ -130,6 +131,9 @@ static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface) if (buffer->draw_buffer) device->upload_map |= 1u << i; } + if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &format, &offset)) + && (buffer = wined3d_buffer_get_parent(wined3d_buffer)) && buffer->draw_buffer) + device->upload_map |= 1u << D3D9_MAX_STREAMS; wined3d_mutex_unlock();
return D3D_OK;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=45651
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- Not much more than a copy of the d3d9 version.
dlls/d3d8/buffer.c | 24 +++++++++++-- dlls/d3d8/d3d8_private.h | 10 ++++-- dlls/d3d8/device.c | 77 ++++++++++++++++++++++++++++++++++++---- 3 files changed, 99 insertions(+), 12 deletions(-)
diff --git a/dlls/d3d8/buffer.c b/dlls/d3d8/buffer.c index 626d74e964c..20efe6bd18a 100644 --- a/dlls/d3d8/buffer.c +++ b/dlls/d3d8/buffer.c @@ -57,6 +57,8 @@ static ULONG WINAPI d3d8_vertexbuffer_AddRef(IDirect3DVertexBuffer8 *iface) IDirect3DDevice8_AddRef(buffer->parent_device); wined3d_mutex_lock(); wined3d_buffer_incref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_incref(buffer->draw_buffer); wined3d_mutex_unlock(); }
@@ -76,6 +78,8 @@ static ULONG WINAPI d3d8_vertexbuffer_Release(IDirect3DVertexBuffer8 *iface)
wined3d_mutex_lock(); wined3d_buffer_decref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_decref(buffer->draw_buffer); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -273,6 +277,7 @@ static const struct wined3d_parent_ops d3d8_vertexbuffer_wined3d_parent_ops = HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device, UINT size, DWORD usage, DWORD fvf, D3DPOOL pool) { + const struct wined3d_parent_ops *parent_ops = &d3d8_null_wined3d_parent_ops; struct wined3d_buffer_desc desc; HRESULT hr;
@@ -292,15 +297,28 @@ HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *
desc.byte_width = size; desc.usage = usage & WINED3DUSAGE_MASK; - desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + desc.bind_flags = 0; desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; desc.misc_flags = 0; desc.structure_byte_stride = 0;
+ if (desc.access & WINED3D_RESOURCE_ACCESS_GPU) + { + desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + parent_ops = &d3d8_vertexbuffer_wined3d_parent_ops; + } + wined3d_mutex_lock(); - hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, - &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, parent_ops, &buffer->wined3d_buffer); + if (SUCCEEDED(hr) && !(desc.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, + &d3d8_vertexbuffer_wined3d_parent_ops, &buffer->draw_buffer))) + wined3d_buffer_decref(buffer->wined3d_buffer); + } wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 7f6049df574..03c3daf0227 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -39,9 +39,14 @@
#define D3DPRESENTFLAGS_MASK 0x00000fffu
+#define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256 +#define D3D8_MAX_STREAMS 16 + /* CreateVertexShader can return > 0xFFFF */ #define VS_HIGHESTFIXEDFXF 0xF0000000
+extern const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops DECLSPEC_HIDDEN; + void d3dcaps_from_wined3dcaps(D3DCAPS8 *caps, const struct wined3d_caps *wined3d_caps) DECLSPEC_HIDDEN;
struct d3d8 @@ -120,6 +125,8 @@ struct d3d8_device LONG device_state; /* Avoids recursion with nested ReleaseRef to 0 */ BOOL inDestruction; + BOOL recording; + unsigned int upload_map;
/* The d3d8 API supports only one implicit swapchain (no D3DCREATE_ADAPTERGROUP_DEVICE, * no GetSwapchain, GetBackBuffer doesn't accept a swapchain number). */ @@ -199,6 +206,7 @@ struct d3d8_vertexbuffer struct d3d8_resource resource; struct wined3d_buffer *wined3d_buffer; IDirect3DDevice8 *parent_device; + struct wined3d_buffer *draw_buffer; DWORD fvf; };
@@ -260,8 +268,6 @@ void d3d8_vertex_shader_destroy(struct d3d8_vertex_shader *shader) DECLSPEC_HIDD HRESULT d3d8_vertex_shader_init(struct d3d8_vertex_shader *shader, struct d3d8_device *device, const DWORD *declaration, const DWORD *byte_code, DWORD shader_handle, DWORD usage) DECLSPEC_HIDDEN;
-#define D3D8_MAX_VERTEX_SHADER_CONSTANTF 256 - struct d3d8_pixel_shader { DWORD handle; diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 3c83811103f..98311250d30 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -36,7 +36,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d8);
static void STDMETHODCALLTYPE d3d8_null_wined3d_object_destroyed(void *parent) {}
-static const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops = +const struct wined3d_parent_ops d3d8_null_wined3d_parent_ops = { d3d8_null_wined3d_object_destroyed, }; @@ -891,6 +891,7 @@ static HRESULT WINAPI d3d8_device_Reset(IDirect3DDevice8 *iface, if (SUCCEEDED(hr = wined3d_device_reset(device->wined3d_device, &swapchain_desc, NULL, reset_enum_callback, TRUE))) { + device->recording = FALSE; present_parameters->BackBufferCount = swapchain_desc.backbuffer_count; device->implicit_swapchain->swap_interval = wined3dswapinterval_from_d3d(present_parameters->FullScreen_PresentationInterval); @@ -1845,7 +1846,8 @@ static HRESULT WINAPI d3d8_device_BeginStateBlock(IDirect3DDevice8 *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); - hr = wined3d_device_begin_stateblock(device->wined3d_device); + if (SUCCEEDED(hr = wined3d_device_begin_stateblock(device->wined3d_device))) + device->recording = TRUE; wined3d_mutex_unlock();
return hr; @@ -1870,6 +1872,7 @@ static HRESULT WINAPI d3d8_device_EndStateBlock(IDirect3DDevice8 *iface, DWORD * wined3d_mutex_unlock(); return hr; } + device->recording = FALSE;
*token = d3d8_allocate_handle(&device->handle_table, stateblock, D3D8_HANDLE_SB); wined3d_mutex_unlock(); @@ -1893,6 +1896,10 @@ static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); struct wined3d_stateblock *stateblock; + struct wined3d_buffer *wined3d_buffer; + struct d3d8_vertexbuffer *buffer; + unsigned int i, offset, stride; + HRESULT hr;
TRACE("iface %p, token %#x.\n", iface, token);
@@ -1908,6 +1915,17 @@ static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD return D3DERR_INVALIDCALL; } wined3d_stateblock_apply(stateblock); + device->upload_map = 0; + for (i = 0; i < D3D8_MAX_STREAMS; ++i) + { + if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, + i, &wined3d_buffer, &offset, &stride))) + continue; + if (!wined3d_buffer || !(buffer = wined3d_buffer_get_parent(wined3d_buffer))) + continue; + if (buffer->draw_buffer) + device->upload_map |= 1u << i; + } wined3d_mutex_unlock();
return D3D_OK; @@ -2229,19 +2247,48 @@ static HRESULT WINAPI d3d8_device_GetCurrentTexturePalette(IDirect3DDevice8 *ifa return D3DERR_INVALIDCALL; }
+static void d3d8_device_upload_sysmem_buffers(struct d3d8_device *device, + unsigned int start_vertex, unsigned int vertex_count) +{ + struct wined3d_box box = {0, 0, 0, 1, 0, 1}; + struct d3d8_vertexbuffer *d3d8_buffer; + unsigned int i, offset, stride, map; + struct wined3d_buffer *dst_buffer; + HRESULT hr; + + map = device->upload_map; + while (map) + { + i = ffs(map) - 1; + map ^= 1u << i; + + if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, i, &dst_buffer, &offset, &stride))) + ERR("Failed to get stream source.\n"); + d3d8_buffer = wined3d_buffer_get_parent(dst_buffer); + box.left = offset + start_vertex * stride; + box.right = box.left + vertex_count * stride; + if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, + wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0, + wined3d_buffer_get_resource(d3d8_buffer->wined3d_buffer), 0, &box, 0))) + ERR("Failed to update buffer.\n"); + } +} + static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); + unsigned int vertex_count; HRESULT hr;
TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n", iface, primitive_type, start_vertex, primitive_count);
+ vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count); wined3d_mutex_lock(); + d3d8_device_upload_sysmem_buffers(device, start_vertex, vertex_count); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); - hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, - vertex_count_from_primitive_count(primitive_type, primitive_count)); + hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count); wined3d_mutex_unlock();
return hr; @@ -2258,6 +2305,7 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface, iface, primitive_type, min_vertex_idx, vertex_count, start_idx, primitive_count);
wined3d_mutex_lock(); + d3d8_device_upload_sysmem_buffers(device, min_vertex_idx, vertex_count); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx, vertex_count_from_primitive_count(primitive_type, primitive_count)); @@ -3098,6 +3146,7 @@ static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface, { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); struct d3d8_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer8(buffer); + struct wined3d_buffer *wined3d_buffer; HRESULT hr;
TRACE("iface %p, stream_idx %u, buffer %p, stride %u.\n", @@ -3106,14 +3155,28 @@ static HRESULT WINAPI d3d8_device_SetStreamSource(IDirect3DDevice8 *iface, wined3d_mutex_lock(); if (!stride) { - struct wined3d_buffer *wined3d_buffer; unsigned int cur_offset;
hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, &cur_offset, &stride); } - hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, - buffer_impl ? buffer_impl->wined3d_buffer : NULL, 0, stride); + + if (!buffer_impl) + wined3d_buffer = NULL; + else if (buffer_impl->draw_buffer) + wined3d_buffer = buffer_impl->draw_buffer; + else + wined3d_buffer = buffer_impl->wined3d_buffer; + + hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, wined3d_buffer, 0, stride); + if (SUCCEEDED(hr) && !device->recording) + { + if (buffer_impl && buffer_impl->draw_buffer) + device->upload_map |= (1u << stream_idx); + else + device->upload_map &= ~(1u << stream_idx); + } + wined3d_mutex_unlock();
return hr;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=45652
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/d3d8/buffer.c | 24 ++++++++++++++++--- dlls/d3d8/d3d8_private.h | 1 + dlls/d3d8/device.c | 51 +++++++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 6 deletions(-)
diff --git a/dlls/d3d8/buffer.c b/dlls/d3d8/buffer.c index 20efe6bd18a..58aaff275b1 100644 --- a/dlls/d3d8/buffer.c +++ b/dlls/d3d8/buffer.c @@ -377,6 +377,8 @@ static ULONG WINAPI d3d8_indexbuffer_AddRef(IDirect3DIndexBuffer8 *iface) IDirect3DDevice8_AddRef(buffer->parent_device); wined3d_mutex_lock(); wined3d_buffer_incref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_incref(buffer->draw_buffer); wined3d_mutex_unlock(); }
@@ -396,6 +398,8 @@ static ULONG WINAPI d3d8_indexbuffer_Release(IDirect3DIndexBuffer8 *iface)
wined3d_mutex_lock(); wined3d_buffer_decref(buffer->wined3d_buffer); + if (buffer->draw_buffer) + wined3d_buffer_decref(buffer->draw_buffer); wined3d_mutex_unlock();
/* Release the device last, as it may cause the device to be destroyed. */ @@ -592,6 +596,7 @@ static const struct wined3d_parent_ops d3d8_indexbuffer_wined3d_parent_ops = HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device, UINT size, DWORD usage, D3DFORMAT format, D3DPOOL pool) { + const struct wined3d_parent_ops *parent_ops = &d3d8_null_wined3d_parent_ops; struct wined3d_buffer_desc desc; HRESULT hr;
@@ -604,19 +609,32 @@ HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *de
desc.byte_width = size; desc.usage = (usage & WINED3DUSAGE_MASK) | WINED3DUSAGE_STATICDECL; - desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + desc.bind_flags = 0; desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; desc.misc_flags = 0; desc.structure_byte_stride = 0;
+ if (desc.access & WINED3D_RESOURCE_ACCESS_GPU) + { + desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + parent_ops = &d3d8_indexbuffer_wined3d_parent_ops; + } + buffer->IDirect3DIndexBuffer8_iface.lpVtbl = &d3d8_indexbuffer_vtbl; d3d8_resource_init(&buffer->resource); buffer->format = wined3dformat_from_d3dformat(format);
wined3d_mutex_lock(); - hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, - &d3d8_indexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer); + hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, parent_ops, &buffer->wined3d_buffer); + if (SUCCEEDED(hr) && !(desc.access & WINED3D_RESOURCE_ACCESS_GPU)) + { + desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; + desc.access = WINED3D_RESOURCE_ACCESS_GPU; + if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, + &d3d8_indexbuffer_wined3d_parent_ops, &buffer->draw_buffer))) + wined3d_buffer_decref(buffer->wined3d_buffer); + } wined3d_mutex_unlock(); if (FAILED(hr)) { diff --git a/dlls/d3d8/d3d8_private.h b/dlls/d3d8/d3d8_private.h index 03c3daf0227..60d70fa3524 100644 --- a/dlls/d3d8/d3d8_private.h +++ b/dlls/d3d8/d3d8_private.h @@ -220,6 +220,7 @@ struct d3d8_indexbuffer struct d3d8_resource resource; struct wined3d_buffer *wined3d_buffer; IDirect3DDevice8 *parent_device; + struct wined3d_buffer *draw_buffer; enum wined3d_format_id format; };
diff --git a/dlls/d3d8/device.c b/dlls/d3d8/device.c index 98311250d30..f5dffe6b707 100644 --- a/dlls/d3d8/device.c +++ b/dlls/d3d8/device.c @@ -1899,6 +1899,7 @@ static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD struct wined3d_buffer *wined3d_buffer; struct d3d8_vertexbuffer *buffer; unsigned int i, offset, stride; + enum wined3d_format_id format; HRESULT hr;
TRACE("iface %p, token %#x.\n", iface, token); @@ -1926,6 +1927,9 @@ static HRESULT WINAPI d3d8_device_ApplyStateBlock(IDirect3DDevice8 *iface, DWORD if (buffer->draw_buffer) device->upload_map |= 1u << i; } + if ((wined3d_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &format, &offset)) + && (buffer = wined3d_buffer_get_parent(wined3d_buffer)) && buffer->draw_buffer) + device->upload_map |= 1u << D3D8_MAX_STREAMS; wined3d_mutex_unlock();
return D3D_OK; @@ -2256,7 +2260,7 @@ static void d3d8_device_upload_sysmem_buffers(struct d3d8_device *device, struct wined3d_buffer *dst_buffer; HRESULT hr;
- map = device->upload_map; + map = device->upload_map & ((1u << D3D8_MAX_STREAMS) - 1); while (map) { i = ffs(map) - 1; @@ -2274,6 +2278,31 @@ static void d3d8_device_upload_sysmem_buffers(struct d3d8_device *device, } }
+static void d3d8_device_upload_sysmem_index_buffer(struct d3d8_device *device, + unsigned int start_idx, unsigned int idx_count) +{ + struct wined3d_box box = {0, 0, 0, 1, 0, 1}; + struct d3d8_vertexbuffer *d3d8_buffer; + struct wined3d_buffer *dst_buffer; + enum wined3d_format_id format; + unsigned int offset, idx_size; + HRESULT hr; + + if (~device->upload_map & (1u << D3D8_MAX_STREAMS)) + return; + + if (!(dst_buffer = wined3d_device_get_index_buffer(device->wined3d_device, &format, &offset))) + ERR("Failed to get index buffer.\n"); + d3d8_buffer = wined3d_buffer_get_parent(dst_buffer); + idx_size = format == WINED3DFMT_R16_UINT ? 2 : 4; + box.left = offset + start_idx * idx_size; + box.right = box.left + idx_count * idx_size; + if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device, + wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0, + wined3d_buffer_get_resource(d3d8_buffer->wined3d_buffer), 0, &box, 0))) + ERR("Failed to update buffer.\n"); +} + static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { @@ -2306,6 +2335,8 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
wined3d_mutex_lock(); d3d8_device_upload_sysmem_buffers(device, min_vertex_idx, vertex_count); + d3d8_device_upload_sysmem_index_buffer(device, start_idx, + vertex_count_from_primitive_count(primitive_type, primitive_count)); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0); hr = wined3d_device_draw_indexed_primitive(device->wined3d_device, start_idx, vertex_count_from_primitive_count(primitive_type, primitive_count)); @@ -2882,9 +2913,17 @@ static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface, { struct d3d8_device *device = impl_from_IDirect3DDevice8(iface); struct d3d8_indexbuffer *ib = unsafe_impl_from_IDirect3DIndexBuffer8(buffer); + struct wined3d_buffer *wined3d_buffer;
TRACE("iface %p, buffer %p, base_vertex_idx %u.\n", iface, buffer, base_vertex_idx);
+ if (!ib) + wined3d_buffer = NULL; + else if (ib->draw_buffer) + wined3d_buffer = ib->draw_buffer; + else + wined3d_buffer = ib->wined3d_buffer; + /* WineD3D takes an INT(due to d3d9), but d3d8 uses UINTs. Do I have to add a check here that * the UINT doesn't cause an overflow in the INT? It seems rather unlikely because such large * vertex buffers can't be created to address them with an index that requires the 32nd bit @@ -2893,8 +2932,14 @@ static HRESULT WINAPI d3d8_device_SetIndices(IDirect3DDevice8 *iface, */ wined3d_mutex_lock(); wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); - wined3d_device_set_index_buffer(device->wined3d_device, - ib ? ib->wined3d_buffer : NULL, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); + wined3d_device_set_index_buffer(device->wined3d_device, wined3d_buffer, ib ? ib->format : WINED3DFMT_UNKNOWN, 0); + if (!device->recording) + { + if (ib && ib->draw_buffer) + device->upload_map |= (1u << D3D8_MAX_STREAMS); + else + device->upload_map &= ~(1u << D3D8_MAX_STREAMS); + } wined3d_mutex_unlock();
return D3D_OK;
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=45653
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45279 Signed-off-by: Matteo Bruni mbruni@codeweavers.com --- dlls/ddraw/device.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-)
diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 0d48c7d704e..6f966d22e77 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -4275,8 +4275,11 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb); - HRESULT hr; + struct wined3d_resource *wined3d_resource; + struct wined3d_map_desc wined3d_map_desc; + struct wined3d_box wined3d_box = {0}; DWORD stride; + HRESULT hr;
TRACE("iface %p, primitive_type %#x, vb %p, start_vertex %u, vertex_count %u, flags %#x.\n", iface, primitive_type, vb, start_vertex, vertex_count, flags); @@ -4289,6 +4292,26 @@ static HRESULT d3d_device7_DrawPrimitiveVB(IDirect3DDevice7 *iface, D3DPRIMITIVE
stride = get_flexible_vertex_size(vb_impl->fvf);
+ if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY) + { + TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, falling back to DrawPrimitive.\n"); + wined3d_mutex_lock(); + wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer); + wined3d_box.left = start_vertex * stride; + wined3d_box.right = (vertex_count - start_vertex) * stride; + if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc, + &wined3d_box, WINED3D_MAP_READ))) + { + wined3d_mutex_unlock(); + return D3DERR_VERTEXBUFFERLOCKED; + } + hr = d3d_device7_DrawPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data, + vertex_count, flags); + wined3d_resource_unmap(wined3d_resource, 0); + wined3d_mutex_unlock(); + return hr; + } + wined3d_mutex_lock(); wined3d_device_set_vertex_declaration(device->wined3d_device, vb_impl->wined3d_declaration); if (FAILED(hr = wined3d_device_set_stream_source(device->wined3d_device, @@ -4366,6 +4389,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, struct d3d_device *device = impl_from_IDirect3DDevice7(iface); struct d3d_vertex_buffer *vb_impl = unsafe_impl_from_IDirect3DVertexBuffer7(vb); DWORD stride = get_flexible_vertex_size(vb_impl->fvf); + struct wined3d_resource *wined3d_resource; struct wined3d_map_desc wined3d_map_desc; struct wined3d_box wined3d_box = {0}; struct wined3d_resource *ib; @@ -4382,6 +4406,24 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, return D3D_OK; }
+ if (vb_impl->Caps & D3DVBCAPS_SYSTEMMEMORY) + { + TRACE("Drawing from D3DVBCAPS_SYSTEMMEMORY vertex buffer, falling back to DrawIndexedPrimitive.\n"); + wined3d_mutex_lock(); + wined3d_resource = wined3d_buffer_get_resource(vb_impl->wined3d_buffer); + if (FAILED(hr = wined3d_resource_map(wined3d_resource, 0, &wined3d_map_desc, + &wined3d_box, WINED3D_MAP_READ))) + { + wined3d_mutex_unlock(); + return D3DERR_VERTEXBUFFERLOCKED; + } + hr = d3d_device7_DrawIndexedPrimitive(iface, primitive_type, vb_impl->fvf, wined3d_map_desc.data, + start_vertex + vertex_count, indices, index_count, flags); + wined3d_resource_unmap(wined3d_resource, 0); + wined3d_mutex_unlock(); + return hr; + } + /* Steps: * 1) Upload the indices to the index buffer * 2) Set the index source
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=45654
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=45650
Your paranoid android.
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
=== debian9 (build log) ===
X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig) X Error of failed request: BadValue (integer parameter out of range for operation) Major opcode of failed request: 140 (RANDR) Minor opcode of failed request: 21 (RRSetCrtcConfig)
On Wed, Dec 12, 2018 at 5:10 PM Matteo Bruni mbruni@codeweavers.com wrote:
+static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device,
unsigned int start_vertex, unsigned int vertex_count)
+{
- struct wined3d_box box = {0, 0, 0, 1, 0, 1};
- struct d3d9_vertexbuffer *d3d9_buffer;
- unsigned int i, offset, stride, map;
- struct wined3d_buffer *dst_buffer;
- HRESULT hr;
- map = device->upload_map;
- while (map)
- {
i = ffs(map) - 1;
map ^= 1u << i;
if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, i, &dst_buffer, &offset, &stride)))
ERR("Failed to get stream source.\n");
d3d9_buffer = wined3d_buffer_get_parent(dst_buffer);
box.left = offset + start_vertex * stride;
box.right = box.left + vertex_count * stride;
if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device,
wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0,
wined3d_buffer_get_resource(d3d9_buffer->wined3d_buffer), 0, &box, 0)))
ERR("Failed to update buffer.\n");
- }
+}
It looks like this might stall the rendering pipeline frequently, i.e. we will be updating the same draw buffers continuously between subsequent draw calls with system memory buffers. I am not sure how important it is in practice.
On Thu, Dec 13, 2018 at 3:07 PM Józef Kucia joseph.kucia@gmail.com wrote:
On Wed, Dec 12, 2018 at 5:10 PM Matteo Bruni mbruni@codeweavers.com wrote:
+static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device,
unsigned int start_vertex, unsigned int vertex_count)
+{
- struct wined3d_box box = {0, 0, 0, 1, 0, 1};
- struct d3d9_vertexbuffer *d3d9_buffer;
- unsigned int i, offset, stride, map;
- struct wined3d_buffer *dst_buffer;
- HRESULT hr;
- map = device->upload_map;
- while (map)
- {
i = ffs(map) - 1;
map ^= 1u << i;
if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, i, &dst_buffer, &offset, &stride)))
ERR("Failed to get stream source.\n");
d3d9_buffer = wined3d_buffer_get_parent(dst_buffer);
box.left = offset + start_vertex * stride;
box.right = box.left + vertex_count * stride;
if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device,
wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0,
wined3d_buffer_get_resource(d3d9_buffer->wined3d_buffer), 0, &box, 0)))
ERR("Failed to update buffer.\n");
- }
+}
It looks like this might stall the rendering pipeline frequently, i.e. we will be updating the same draw buffers continuously between subsequent draw calls with system memory buffers. I am not sure how important it is in practice.
That is true. I'm not sure either, I don't expect performance with SYSMEM buffer draws to be critical and restoring functionality is more important anyway. But yes, I think this is fine for a first pass, but probably a TODO comment somewhere would have been nice.
FWIW if it turns out we need the performance, my preferred way of getting that would involve some wined3d work. Specifically, adding support to the NOOVERWRITE / DISCARD flags to wined3d_device_copy_sub_resource_region(), mirroring CopySubresourceRegion1() from d3d11.1.
On Thu, Dec 13, 2018 at 6:22 PM Matteo Bruni matteo.mystral@gmail.com wrote:
On Thu, Dec 13, 2018 at 3:07 PM Józef Kucia joseph.kucia@gmail.com wrote:
It looks like this might stall the rendering pipeline frequently, i.e. we will be updating the same draw buffers continuously between subsequent draw calls with system memory buffers. I am not sure how important it is in practice.
That is true. I'm not sure either, I don't expect performance with SYSMEM buffer draws to be critical and restoring functionality is more important anyway. But yes, I think this is fine for a first pass, but probably a TODO comment somewhere would have been nice.
Definitely, it would be highly desired to restore functionality before the final 4.0 :-)
On Thu, 13 Dec 2018 at 17:37, Józef Kucia joseph.kucia@gmail.com wrote:
It looks like this might stall the rendering pipeline frequently, i.e. we will be updating the same draw buffers continuously between subsequent draw calls with system memory buffers. I am not sure how important it is in practice.
Yeah, there's room for improvement if we care about performance here. I suspect that if you're drawing from D3DPOOL_SYSTEMMEM buffers you've already lost though.
Hi,
Why not always allocate SYSTEMMEM buffers into GPU memory ? For example, GTT memory (without WC, thus fast cpu read), with persistent flags, which means you don't need to unlock. Then no upload is needed.
Yours,
Axel
On 12/12/2018 17:09, Matteo Bruni wrote:
From: Henri Verbeet hverbeet@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45486 Signed-off-by: Matteo Bruni mbruni@codeweavers.com
dlls/d3d9/buffer.c | 24 ++++++++++++++-- dlls/d3d9/d3d9_private.h | 4 +++ dlls/d3d9/device.c | 60 ++++++++++++++++++++++++++++++++++++---- dlls/d3d9/stateblock.c | 17 ++++++++++++ 4 files changed, 96 insertions(+), 9 deletions(-)
diff --git a/dlls/d3d9/buffer.c b/dlls/d3d9/buffer.c index 02b3570402f..15b7e2bdbce 100644 --- a/dlls/d3d9/buffer.c +++ b/dlls/d3d9/buffer.c @@ -59,6 +59,8 @@ static ULONG WINAPI d3d9_vertexbuffer_AddRef(IDirect3DVertexBuffer9 *iface) IDirect3DDevice9Ex_AddRef(buffer->parent_device); wined3d_mutex_lock(); wined3d_buffer_incref(buffer->wined3d_buffer);
if (buffer->draw_buffer)
wined3d_buffer_incref(buffer->draw_buffer); wined3d_mutex_unlock(); }
@@ -78,6 +80,8 @@ static ULONG WINAPI d3d9_vertexbuffer_Release(IDirect3DVertexBuffer9 *iface)
wined3d_mutex_lock(); wined3d_buffer_decref(buffer->wined3d_buffer);
if (buffer->draw_buffer)
wined3d_buffer_decref(buffer->draw_buffer); wined3d_mutex_unlock(); /* Release the device last, as it may cause the device to be destroyed. */
@@ -274,6 +278,7 @@ static const struct wined3d_parent_ops d3d9_vertexbuffer_wined3d_parent_ops = HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *device, UINT size, UINT usage, DWORD fvf, D3DPOOL pool) {
- const struct wined3d_parent_ops *parent_ops = &d3d9_null_wined3d_parent_ops; struct wined3d_buffer_desc desc; HRESULT hr;
@@ -299,15 +304,28 @@ HRESULT vertexbuffer_init(struct d3d9_vertexbuffer *buffer, struct d3d9_device *
desc.byte_width = size; desc.usage = usage & WINED3DUSAGE_MASK;
- desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
desc.bind_flags = 0; desc.access = wined3daccess_from_d3dpool(pool, usage) | WINED3D_RESOURCE_ACCESS_MAP_R | WINED3D_RESOURCE_ACCESS_MAP_W; desc.misc_flags = 0; desc.structure_byte_stride = 0;
if (desc.access & WINED3D_RESOURCE_ACCESS_GPU)
{
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
parent_ops = &d3d9_vertexbuffer_wined3d_parent_ops;
}
wined3d_mutex_lock();
- hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer,
&d3d9_vertexbuffer_wined3d_parent_ops, &buffer->wined3d_buffer);
- hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer, parent_ops, &buffer->wined3d_buffer);
- if (SUCCEEDED(hr) && !(desc.access & WINED3D_RESOURCE_ACCESS_GPU))
- {
desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER;
desc.access = WINED3D_RESOURCE_ACCESS_GPU;
if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, NULL, buffer,
&d3d9_vertexbuffer_wined3d_parent_ops, &buffer->draw_buffer)))
wined3d_buffer_decref(buffer->wined3d_buffer);
- } wined3d_mutex_unlock(); if (FAILED(hr)) {
diff --git a/dlls/d3d9/d3d9_private.h b/dlls/d3d9/d3d9_private.h index d6155eba60b..8647aac4af1 100644 --- a/dlls/d3d9/d3d9_private.h +++ b/dlls/d3d9/d3d9_private.h @@ -42,6 +42,7 @@
#define D3D9_MAX_VERTEX_SHADER_CONSTANTF 256 #define D3D9_MAX_TEXTURE_UNITS 20 +#define D3D9_MAX_STREAMS 16
#define D3DPRESENTFLAGS_MASK 0x00000fffu
@@ -105,6 +106,8 @@ struct d3d9_device BOOL in_destruction; BOOL in_scene; BOOL has_vertex_declaration;
BOOL recording;
unsigned int upload_map;
unsigned int max_user_clip_planes;
@@ -181,6 +184,7 @@ struct d3d9_vertexbuffer struct d3d9_resource resource; struct wined3d_buffer *wined3d_buffer; IDirect3DDevice9Ex *parent_device;
- struct wined3d_buffer *draw_buffer; DWORD fvf; };
diff --git a/dlls/d3d9/device.c b/dlls/d3d9/device.c index f19e2ae6f65..7c488bfd601 100644 --- a/dlls/d3d9/device.c +++ b/dlls/d3d9/device.c @@ -974,6 +974,7 @@ static HRESULT d3d9_device_reset(struct d3d9_device *device,
if (!extended) {
device->recording = FALSE; wined3d_device_set_render_state(device->wined3d_device, WINED3D_RS_ZENABLE, !!swapchain_desc.enable_auto_depth_stencil); }
@@ -2317,7 +2318,8 @@ static HRESULT WINAPI d3d9_device_BeginStateBlock(IDirect3DDevice9Ex *iface) TRACE("iface %p.\n", iface);
wined3d_mutex_lock();
- hr = wined3d_device_begin_stateblock(device->wined3d_device);
if (SUCCEEDED(hr = wined3d_device_begin_stateblock(device->wined3d_device)))
device->recording = TRUE; wined3d_mutex_unlock(); return hr;
@@ -2340,6 +2342,7 @@ static HRESULT WINAPI d3d9_device_EndStateBlock(IDirect3DDevice9Ex *iface, IDire WARN("Failed to end the state block, hr %#x.\n", hr); return hr; }
device->recording = FALSE;
if (!(object = heap_alloc_zero(sizeof(*object)))) {
@@ -2688,10 +2691,38 @@ static void d3d9_generate_auto_mipmaps(struct d3d9_device *device) } }
+static void d3d9_device_upload_sysmem_buffers(struct d3d9_device *device,
unsigned int start_vertex, unsigned int vertex_count)
+{
- struct wined3d_box box = {0, 0, 0, 1, 0, 1};
- struct d3d9_vertexbuffer *d3d9_buffer;
- unsigned int i, offset, stride, map;
- struct wined3d_buffer *dst_buffer;
- HRESULT hr;
- map = device->upload_map;
- while (map)
- {
i = ffs(map) - 1;
map ^= 1u << i;
if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device, i, &dst_buffer, &offset, &stride)))
ERR("Failed to get stream source.\n");
d3d9_buffer = wined3d_buffer_get_parent(dst_buffer);
box.left = offset + start_vertex * stride;
box.right = box.left + vertex_count * stride;
if (FAILED(hr = wined3d_device_copy_sub_resource_region(device->wined3d_device,
wined3d_buffer_get_resource(dst_buffer), 0, box.left, 0, 0,
wined3d_buffer_get_resource(d3d9_buffer->wined3d_buffer), 0, &box, 0)))
ERR("Failed to update buffer.\n");
- }
+}
static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, D3DPRIMITIVETYPE primitive_type, UINT start_vertex, UINT primitive_count) { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface);
unsigned int vertex_count; HRESULT hr;
TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
@@ -2704,10 +2735,11 @@ static HRESULT WINAPI d3d9_device_DrawPrimitive(IDirect3DDevice9Ex *iface, WARN("Called without a valid vertex declaration set.\n"); return D3DERR_INVALIDCALL; }
- vertex_count = vertex_count_from_primitive_count(primitive_type, primitive_count);
- d3d9_device_upload_sysmem_buffers(device, start_vertex, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
- hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex,
vertex_count_from_primitive_count(primitive_type, primitive_count));
- hr = wined3d_device_draw_primitive(device->wined3d_device, start_vertex, vertex_count); if (SUCCEEDED(hr)) d3d9_rts_flag_auto_gen_mipmap(device); wined3d_mutex_unlock();
@@ -2734,6 +2766,7 @@ static HRESULT WINAPI d3d9_device_DrawIndexedPrimitive(IDirect3DDevice9Ex *iface WARN("Called without a valid vertex declaration set.\n"); return D3DERR_INVALIDCALL; }
- d3d9_device_upload_sysmem_buffers(device, min_vertex_idx, vertex_count); d3d9_generate_auto_mipmaps(device); wined3d_device_set_base_vertex_index(device->wined3d_device, base_vertex_idx); wined3d_device_set_primitive_type(device->wined3d_device, primitive_type, 0);
@@ -3378,6 +3411,7 @@ static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, { struct d3d9_device *device = impl_from_IDirect3DDevice9Ex(iface); struct d3d9_vertexbuffer *buffer_impl = unsafe_impl_from_IDirect3DVertexBuffer9(buffer);
struct wined3d_buffer *wined3d_buffer; HRESULT hr;
TRACE("iface %p, stream_idx %u, buffer %p, offset %u, stride %u.\n",
@@ -3386,14 +3420,28 @@ static HRESULT WINAPI d3d9_device_SetStreamSource(IDirect3DDevice9Ex *iface, wined3d_mutex_lock(); if (!stride) {
struct wined3d_buffer *wined3d_buffer; unsigned int cur_offset; hr = wined3d_device_get_stream_source(device->wined3d_device, stream_idx, &wined3d_buffer, &cur_offset, &stride); }
hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx,
buffer_impl ? buffer_impl->wined3d_buffer : NULL, offset, stride);
if (!buffer_impl)
wined3d_buffer = NULL;
else if (buffer_impl->draw_buffer)
wined3d_buffer = buffer_impl->draw_buffer;
else
wined3d_buffer = buffer_impl->wined3d_buffer;
hr = wined3d_device_set_stream_source(device->wined3d_device, stream_idx, wined3d_buffer, offset, stride);
if (SUCCEEDED(hr) && !device->recording)
{
if (buffer_impl && buffer_impl->draw_buffer)
device->upload_map |= (1u << stream_idx);
else
device->upload_map &= ~(1u << stream_idx);
}
wined3d_mutex_unlock(); return hr;
diff --git a/dlls/d3d9/stateblock.c b/dlls/d3d9/stateblock.c index 62b3bacb28d..c5306fd80b3 100644 --- a/dlls/d3d9/stateblock.c +++ b/dlls/d3d9/stateblock.c @@ -108,11 +108,28 @@ static HRESULT WINAPI d3d9_stateblock_Capture(IDirect3DStateBlock9 *iface) static HRESULT WINAPI d3d9_stateblock_Apply(IDirect3DStateBlock9 *iface) { struct d3d9_stateblock *stateblock = impl_from_IDirect3DStateBlock9(iface);
struct wined3d_buffer *wined3d_buffer;
struct d3d9_vertexbuffer *buffer;
unsigned int i, offset, stride;
struct d3d9_device *device;
HRESULT hr;
TRACE("iface %p.\n", iface);
wined3d_mutex_lock(); wined3d_stateblock_apply(stateblock->wined3d_stateblock);
device = impl_from_IDirect3DDevice9Ex(stateblock->parent_device);
device->upload_map = 0;
for (i = 0; i < D3D9_MAX_STREAMS; ++i)
{
if (FAILED(hr = wined3d_device_get_stream_source(device->wined3d_device,
i, &wined3d_buffer, &offset, &stride)))
continue;
if (!wined3d_buffer || !(buffer = wined3d_buffer_get_parent(wined3d_buffer)))
continue;
if (buffer->draw_buffer)
device->upload_map |= 1u << i;
} wined3d_mutex_unlock();
return D3D_OK;
On Thu, Dec 13, 2018 at 6:30 PM Axel Davy davyaxel0@gmail.com wrote:
Hi,
Why not always allocate SYSTEMMEM buffers into GPU memory ? For example, GTT memory (without WC, thus fast cpu read), with persistent flags, which means you don't need to unlock. Then no upload is needed.
That's more along the lines of the previous patchset and AMD's native way of supporting this. This one takes the Nvidia approach and doesn't require changes to wined3d, which I think is preferable, especially now that we are in code freeze.
On Thu, 13 Dec 2018 at 21:00, Axel Davy davyaxel0@gmail.com wrote:
Why not always allocate SYSTEMMEM buffers into GPU memory ? For example, GTT memory (without WC, thus fast cpu read), with persistent flags, which means you don't need to unlock. Then no upload is needed.
What Matteo said, but also because the documentation claims that pretty much the only reason for drawing from D3DPOOL_SYSTEMMEM buffers (as opposed to DEFAULT+DYNAMIC) is to limit GTT memory usage.
Henri
On 17/12/2018 21:42, Henri Verbeet wrote:
On Thu, 13 Dec 2018 at 21:00, Axel Davy davyaxel0@gmail.com wrote:
Why not always allocate SYSTEMMEM buffers into GPU memory ? For example, GTT memory (without WC, thus fast cpu read), with persistent flags, which means you don't need to unlock. Then no upload is needed.
What Matteo said, but also because the documentation claims that pretty much the only reason for drawing from D3DPOOL_SYSTEMMEM buffers (as opposed to DEFAULT+DYNAMIC) is to limit GTT memory usage.
Henri
I couldn't find the results of the tests we ran for locking flags and behaviors when doing double lock, or lock write draw write unlock, though I have the patch if you are interested to run it.
In the code I see the following comments which should be interesting for your implementation (I don't remember if the comments are true for all vendors or only on one):
(Test drawing with data write outside of locked area - after a first draw)
* Test shows that buffers start dirty: * The whole buffer is uploaded before first draw call. * Test shows that D3DPOOL_DEFAULT and D3DPOOL_SYSTEMMEM are always * locked RW and the whole buffer is uploaded. * Test shows that D3DPOOL_MANAGED is always locked RW and only the region * locked is marked dirty and uploaded (except after creation).
(Test drawing while locked) * Test shows that it is possible to draw using a locked buffer and no error is generated. * For D3DPOOL_SYSTEMMEM the content of the buffer at draw call is used, for other * pools it is possible that the upload takes longer than the draw call. (race condition)
To me using GTT looks good for SYSTEMMEM. You can also do an upload, but you must be careful.
Axel