From: Anton Baskanov baskanov@gmail.com
--- dlls/wined3d/buffer.c | 108 ++++++++++++++++++++++++++++++--- dlls/wined3d/wined3d.spec | 1 + dlls/wined3d/wined3d_private.h | 3 + include/wine/wined3d.h | 19 ++++++ 4 files changed, 124 insertions(+), 7 deletions(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index 1a953f8e218..babbd0d0968 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -1685,8 +1685,9 @@ static HRESULT wined3d_streaming_buffer_prepare(struct wined3d_device *device, return hr; }
-HRESULT CDECL wined3d_streaming_buffer_upload(struct wined3d_device *device, struct wined3d_streaming_buffer *buffer, - const void *data, unsigned int size, unsigned int stride, unsigned int *ret_pos) +static HRESULT wined3d_streaming_buffer_map(struct wined3d_device *device, + struct wined3d_streaming_buffer *buffer, unsigned int size, unsigned int stride, + void **ret_data, unsigned int *ret_pos) { unsigned int map_flags = WINED3D_MAP_WRITE; struct wined3d_resource *resource; @@ -1695,9 +1696,6 @@ HRESULT CDECL wined3d_streaming_buffer_upload(struct wined3d_device *device, str struct wined3d_box box; HRESULT hr;
- TRACE("device %p, buffer %p, data %p, size %u, stride %u, ret_pos %p.\n", - device, buffer, data, size, stride, ret_pos); - if (FAILED(hr = wined3d_streaming_buffer_prepare(device, buffer, size))) return hr; resource = &buffer->buffer->resource; @@ -1719,8 +1717,104 @@ HRESULT CDECL wined3d_streaming_buffer_upload(struct wined3d_device *device, str wined3d_box_set(&box, pos, 0, pos + size, 1, 0, 1); if (SUCCEEDED(hr = wined3d_resource_map(resource, 0, &map_desc, &box, map_flags))) { - memcpy(map_desc.data, data, size); - wined3d_resource_unmap(resource, 0); + *ret_data = map_desc.data; + *ret_pos = pos; + } + return hr; +} + +HRESULT CDECL wined3d_streaming_buffer_upload(struct wined3d_device *device, struct wined3d_streaming_buffer *buffer, + const void *data, unsigned int size, unsigned int stride, unsigned int *ret_pos) +{ + unsigned int pos; + void *dst_data; + HRESULT hr; + + TRACE("device %p, buffer %p, data %p, size %u, stride %u, ret_pos %p.\n", + device, buffer, data, size, stride, ret_pos); + + if (SUCCEEDED(hr = wined3d_streaming_buffer_map(device, buffer, size, stride, &dst_data, &pos))) + { + memcpy(dst_data, data, size); + wined3d_resource_unmap(&buffer->buffer->resource, 0); + *ret_pos = pos; + buffer->pos = pos + size; + } + return hr; +} + +static void pack_strided_data(BYTE *dst, unsigned int count, const struct wined3d_draw_primitive_strided_data *src, DWORD fvf) +{ + DWORD i, tex, offset; + + for (i = 0; i < count; i++) + { + /* The contents of the strided data are determined by the fvf, + * not by the members set in src. So it's valid + * to have diffuse.data set to 0xdeadbeef if the diffuse flag is + * not set in the fvf. */ + if (fvf & WINED3DFVF_POSITION_MASK) + { + offset = i * src->position.stride; + if (fvf & WINED3DFVF_XYZRHW) + { + memcpy(dst, ((BYTE *)src->position.data) + offset, 4 * sizeof(float)); + dst += 4 * sizeof(float); + } + else + { + memcpy(dst, ((BYTE *)src->position.data) + offset, 3 * sizeof(float)); + dst += 3 * sizeof(float); + } + } + + if (fvf & WINED3DFVF_NORMAL) + { + offset = i * src->normal.stride; + memcpy(dst, ((BYTE *)src->normal.data) + offset, 3 * sizeof(float)); + dst += 3 * sizeof(float); + } + + if (fvf & WINED3DFVF_DIFFUSE) + { + offset = i * src->diffuse.stride; + memcpy(dst, ((BYTE *)src->diffuse.data) + offset, sizeof(DWORD)); + dst += sizeof(DWORD); + } + + if (fvf & WINED3DFVF_SPECULAR) + { + offset = i * src->specular.stride; + memcpy(dst, ((BYTE *)src->specular.data) + offset, sizeof(DWORD)); + dst += sizeof(DWORD); + } + + for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex) + { + DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex); + offset = i * src->texcoords[tex].stride; + memcpy(dst, ((BYTE *)src->texcoords[tex].data) + offset, attrib_count * sizeof(float)); + dst += attrib_count * sizeof(float); + } + } +} + +HRESULT CDECL wined3d_streaming_buffer_upload_strided(struct wined3d_device *device, struct wined3d_streaming_buffer *buffer, + DWORD fvf, const struct wined3d_draw_primitive_strided_data *data, unsigned int count, unsigned int stride, unsigned int *ret_pos) +{ + unsigned int size, pos; + void *dst_data; + HRESULT hr; + + TRACE("device %p, buffer %p, fvf %x, data %p, count %u, ret_pos %p.\n", + device, buffer, fvf, data, count, ret_pos); + + size = count * stride; + + if (SUCCEEDED(hr = wined3d_streaming_buffer_map(device, buffer, size, stride, &dst_data, &pos))) + { + pack_strided_data(dst_data, count, data, fvf); + wined3d_resource_unmap(&buffer->buffer->resource, 0); *ret_pos = pos; buffer->pos = pos + size; } diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index e6126faf838..ee65fc7d4db 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -261,6 +261,7 @@ @ cdecl wined3d_stateblock_set_vs_consts_i(ptr long long ptr)
@ cdecl wined3d_streaming_buffer_upload(ptr ptr ptr long long ptr) +@ cdecl wined3d_streaming_buffer_upload_strided(ptr ptr long ptr long long ptr)
@ cdecl wined3d_swapchain_create(ptr ptr ptr ptr ptr ptr) @ cdecl wined3d_swapchain_decref(ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index b7d3b579ed2..7c7279434ba 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1864,6 +1864,9 @@ void dispatch_compute(struct wined3d_device *device, const struct wined3d_state
#define eps 1e-8f
+#define GET_TEXCOUNT_FROM_FVF(d3dvtVertexType) \ + (((d3dvtVertexType) & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT) + #define GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, tex_num) \ (((((d3dvtVertexType) >> (16 + (2 * (tex_num)))) + 1) & 0x03) + 1)
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index a18dcda45be..5bb93aa720c 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -1593,6 +1593,8 @@ enum wined3d_memory_segment_group #define WINED3D_MAX_RENDER_TARGETS 8 #define WINED3D_MAX_CONSTANT_BUFFER_SIZE 4096
+#define WINED3D_DP_MAX_TEXCOORDS 8 + struct wined3d_display_mode { UINT width; @@ -2283,6 +2285,21 @@ struct wined3d_streaming_buffer unsigned int bind_flags; };
+struct wined3d_dp_ptr_stride +{ + void *data; + DWORD stride; +}; + +struct wined3d_draw_primitive_strided_data +{ + struct wined3d_dp_ptr_stride position; + struct wined3d_dp_ptr_stride normal; + struct wined3d_dp_ptr_stride diffuse; + struct wined3d_dp_ptr_stride specular; + struct wined3d_dp_ptr_stride texcoords[WINED3D_DP_MAX_TEXCOORDS]; +}; + void __stdcall wined3d_mutex_lock(void); void __stdcall wined3d_mutex_unlock(void);
@@ -2790,6 +2807,8 @@ HRESULT __cdecl wined3d_stateblock_set_vs_consts_i(struct wined3d_stateblock *st
HRESULT __cdecl wined3d_streaming_buffer_upload(struct wined3d_device *device, struct wined3d_streaming_buffer *buffer, const void *data, unsigned int size, unsigned int stride, unsigned int *pos); +HRESULT __cdecl wined3d_streaming_buffer_upload_strided(struct wined3d_device *device, struct wined3d_streaming_buffer *buffer, + DWORD fvf, const struct wined3d_draw_primitive_strided_data *data, unsigned int count, unsigned int stride, unsigned int *pos);
HRESULT __cdecl wined3d_swapchain_create(struct wined3d_device *device, struct wined3d_swapchain_desc *desc, struct wined3d_swapchain_state_parent *state_parent,
From: Anton Baskanov baskanov@gmail.com
--- dlls/ddraw/ddraw_private.h | 4 +- dlls/ddraw/device.c | 217 +++++-------------------------------- 2 files changed, 26 insertions(+), 195 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index 1edc459ed79..d2b1fc495fc 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -339,9 +339,7 @@ struct d3d_device UINT index_buffer_size; UINT index_buffer_pos;
- struct wined3d_buffer *vertex_buffer; - UINT vertex_buffer_size; - UINT vertex_buffer_pos; + struct wined3d_streaming_buffer vertex_buffer;
/* Viewport management */ struct list viewport_list; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 27b650036cf..9049f843ab0 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -281,8 +281,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface)
if (This->index_buffer) wined3d_buffer_decref(This->index_buffer); - if (This->vertex_buffer) - wined3d_buffer_decref(This->vertex_buffer); + wined3d_streaming_buffer_cleanup(&This->vertex_buffer);
wined3d_device_context_set_rendertarget_views(This->immediate_context, 0, 1, &null_rtv, FALSE);
@@ -3391,44 +3390,6 @@ static HRESULT WINAPI d3d_device2_MultiplyTransform(IDirect3DDevice2 *iface, * DDERR_INVALIDPARAMS if Vertices is NULL * *****************************************************************************/ - -/* The caller is responsible for wined3d locking */ -static HRESULT d3d_device_prepare_vertex_buffer(struct d3d_device *device, UINT min_size) -{ - HRESULT hr; - - if (device->vertex_buffer_size < min_size || !device->vertex_buffer) - { - UINT size = max(device->vertex_buffer_size * 2, min_size); - struct wined3d_buffer_desc desc; - struct wined3d_buffer *buffer; - - TRACE("Growing vertex buffer to %u bytes\n", size); - - desc.byte_width = size; - desc.usage = WINED3DUSAGE_DYNAMIC; - desc.bind_flags = WINED3D_BIND_VERTEX_BUFFER; - desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W; - desc.misc_flags = 0; - desc.structure_byte_stride = 0; - - if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, - NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer))) - { - ERR("Failed to create vertex buffer, hr %#lx.\n", hr); - return hr; - } - - if (device->vertex_buffer) - wined3d_buffer_decref(device->vertex_buffer); - - device->vertex_buffer = buffer; - device->vertex_buffer_size = size; - device->vertex_buffer_pos = 0; - } - return D3D_OK; -} - static void d3d_device_sync_rendertarget(struct d3d_device *device) { struct wined3d_rendertarget_view *rtv; @@ -3475,10 +3436,7 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, DWORD vertex_count, DWORD flags) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); - struct wined3d_map_desc wined3d_map_desc; - struct wined3d_box wined3d_box = {0}; - UINT stride, vb_pos, size, align; - struct wined3d_resource *vb; + UINT stride, vb_pos, size; HRESULT hr;
TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, flags %#lx.\n", @@ -3495,29 +3453,12 @@ static HRESULT d3d_device7_DrawPrimitive(IDirect3DDevice7 *iface, size = vertex_count * stride;
wined3d_mutex_lock(); - hr = d3d_device_prepare_vertex_buffer(device, size); - if (FAILED(hr)) - goto done; - - vb_pos = device->vertex_buffer_pos; - align = vb_pos % stride; - if (align) align = stride - align; - if (vb_pos + size + align > device->vertex_buffer_size) - vb_pos = 0; - else - vb_pos += align;
- wined3d_box.left = vb_pos; - wined3d_box.right = vb_pos + size; - vb = wined3d_buffer_get_resource(device->vertex_buffer); - if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device, + &device->vertex_buffer, vertices, size, stride, &vb_pos))) goto done; - memcpy(wined3d_map_desc.data, vertices, size); - wined3d_resource_unmap(vb, 0); - device->vertex_buffer_pos = vb_pos + size;
- hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride); + hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, stride); if (FAILED(hr)) goto done;
@@ -3674,8 +3615,8 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices); struct wined3d_map_desc wined3d_map_desc; struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *ib, *vb; - UINT vb_pos, ib_pos, align; + struct wined3d_resource *ib; + UINT vb_pos, ib_pos;
TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, " "indices %p, index_count %lu, flags %#lx.\n", @@ -3690,27 +3631,9 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, /* Set the D3DDevice's FVF */ wined3d_mutex_lock();
- hr = d3d_device_prepare_vertex_buffer(device, vtx_size); - if (FAILED(hr)) - goto done; - - vb_pos = device->vertex_buffer_pos; - align = vb_pos % stride; - if (align) align = stride - align; - if (vb_pos + vtx_size + align > device->vertex_buffer_size) - vb_pos = 0; - else - vb_pos += align; - - wined3d_box.left = vb_pos; - wined3d_box.right = vb_pos + vtx_size; - vb = wined3d_buffer_get_resource(device->vertex_buffer); - if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device, + &device->vertex_buffer, vertices, vtx_size, stride, &vb_pos))) goto done; - memcpy(wined3d_map_desc.data, vertices, vtx_size); - wined3d_resource_unmap(vb, 0); - device->vertex_buffer_pos = vb_pos + vtx_size;
hr = d3d_device_prepare_index_buffer(device, idx_size); if (FAILED(hr)) @@ -3729,7 +3652,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, wined3d_resource_unmap(ib, 0); device->index_buffer_pos = ib_pos + idx_size;
- hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, stride); + hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, stride); if (FAILED(hr)) goto done; wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT); @@ -3959,73 +3882,13 @@ static HRESULT WINAPI d3d_device2_GetClipStatus(IDirect3DDevice2 *iface, D3DCLIP * (DDERR_INVALIDPARAMS if D3DDrawPrimStrideData is NULL) * *****************************************************************************/ -static void pack_strided_data(BYTE *dst, DWORD count, const D3DDRAWPRIMITIVESTRIDEDDATA *src, DWORD fvf) -{ - DWORD i, tex, offset; - - for (i = 0; i < count; i++) - { - /* The contents of the strided data are determined by the fvf, - * not by the members set in src. So it's valid - * to have diffuse.lpvData set to 0xdeadbeef if the diffuse flag is - * not set in the fvf. */ - if (fvf & D3DFVF_POSITION_MASK) - { - offset = i * src->position.dwStride; - if (fvf & D3DFVF_XYZRHW) - { - memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 4 * sizeof(float)); - dst += 4 * sizeof(float); - } - else - { - memcpy(dst, ((BYTE *)src->position.lpvData) + offset, 3 * sizeof(float)); - dst += 3 * sizeof(float); - } - } - - if (fvf & D3DFVF_NORMAL) - { - offset = i * src->normal.dwStride; - memcpy(dst, ((BYTE *)src->normal.lpvData) + offset, 3 * sizeof(float)); - dst += 3 * sizeof(float); - } - - if (fvf & D3DFVF_DIFFUSE) - { - offset = i * src->diffuse.dwStride; - memcpy(dst, ((BYTE *)src->diffuse.lpvData) + offset, sizeof(DWORD)); - dst += sizeof(DWORD); - } - - if (fvf & D3DFVF_SPECULAR) - { - offset = i * src->specular.dwStride; - memcpy(dst, ((BYTE *)src->specular.lpvData) + offset, sizeof(DWORD)); - dst += sizeof(DWORD); - } - - for (tex = 0; tex < GET_TEXCOUNT_FROM_FVF(fvf); ++tex) - { - DWORD attrib_count = GET_TEXCOORD_SIZE_FROM_FVF(fvf, tex); - offset = i * src->textureCoords[tex].dwStride; - memcpy(dst, ((BYTE *)src->textureCoords[tex].lpvData) + offset, attrib_count * sizeof(float)); - dst += attrib_count * sizeof(float); - } - } -} - static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, D3DDRAWPRIMITIVESTRIDEDDATA *strided_data, DWORD vertex_count, DWORD flags) { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); HRESULT hr; UINT dst_stride = get_flexible_vertex_size(fvf); - UINT dst_size = dst_stride * vertex_count; - struct wined3d_map_desc wined3d_map_desc; - struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *vb; - UINT vb_pos, align; + UINT vb_pos;
TRACE("iface %p, primitive_type %#x, fvf %#lx, strided_data %p, vertex_count %lu, flags %#lx.\n", iface, primitive_type, fvf, strided_data, vertex_count, flags); @@ -4037,29 +3900,14 @@ static HRESULT d3d_device7_DrawPrimitiveStrided(IDirect3DDevice7 *iface, D3DPRIM }
wined3d_mutex_lock(); - hr = d3d_device_prepare_vertex_buffer(device, dst_size); - if (FAILED(hr)) - goto done;
- vb_pos = device->vertex_buffer_pos; - align = vb_pos % dst_stride; - if (align) align = dst_stride - align; - if (vb_pos + dst_size + align > device->vertex_buffer_size) - vb_pos = 0; - else - vb_pos += align; - - wined3d_box.left = vb_pos; - wined3d_box.right = vb_pos + dst_size; - vb = wined3d_buffer_get_resource(device->vertex_buffer); - if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + /* Note: D3DDRAWPRIMITIVESTRIDEDDATA is compatible with struct wined3d_draw_primitive_strided_data. */ + if (FAILED(hr = wined3d_streaming_buffer_upload_strided(device->wined3d_device, + &device->vertex_buffer, fvf, (struct wined3d_draw_primitive_strided_data *)strided_data, + vertex_count, dst_stride, &vb_pos))) goto done; - pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf); - wined3d_resource_unmap(vb, 0); - device->vertex_buffer_pos = vb_pos + dst_size;
- hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, dst_stride); + hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, dst_stride); if (FAILED(hr)) goto done; wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf)); @@ -4135,12 +3983,11 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, { struct d3d_device *device = impl_from_IDirect3DDevice7(iface); UINT vtx_dst_stride = get_flexible_vertex_size(fvf); - UINT vtx_dst_size = vertex_count * vtx_dst_stride; UINT idx_size = index_count * sizeof(WORD); struct wined3d_map_desc wined3d_map_desc; struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *ib, *vb; - UINT vb_pos, align; + struct wined3d_resource *ib; + UINT vb_pos; UINT ib_pos; HRESULT hr;
@@ -4156,28 +4003,12 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface,
wined3d_mutex_lock();
- hr = d3d_device_prepare_vertex_buffer(device, vtx_dst_size); - if (FAILED(hr)) + /* Note: D3DDRAWPRIMITIVESTRIDEDDATA is compatible with struct wined3d_draw_primitive_strided_data. */ + if (FAILED(hr = wined3d_streaming_buffer_upload_strided(device->wined3d_device, + &device->vertex_buffer, fvf, (struct wined3d_draw_primitive_strided_data *)strided_data, + vertex_count, vtx_dst_stride, &vb_pos))) goto done;
- vb_pos = device->vertex_buffer_pos; - align = vb_pos % vtx_dst_stride; - if (align) align = vtx_dst_stride - align; - if (vb_pos + vtx_dst_size + align > device->vertex_buffer_size) - vb_pos = 0; - else - vb_pos += align; - - wined3d_box.left = vb_pos; - wined3d_box.right = vb_pos + vtx_dst_size; - vb = wined3d_buffer_get_resource(device->vertex_buffer); - if (FAILED(hr = wined3d_resource_map(vb, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (vb_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) - goto done; - pack_strided_data(wined3d_map_desc.data, vertex_count, strided_data, fvf); - wined3d_resource_unmap(vb, 0); - device->vertex_buffer_pos = vb_pos + vtx_dst_size; - hr = d3d_device_prepare_index_buffer(device, idx_size); if (FAILED(hr)) goto done; @@ -4195,7 +4026,7 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, wined3d_resource_unmap(ib, 0); device->index_buffer_pos = ib_pos + idx_size;
- hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer, 0, vtx_dst_stride); + hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, vtx_dst_stride); if (FAILED(hr)) goto done; wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT); @@ -7052,6 +6883,8 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c device->stateblock_state = ddraw->stateblock_state; wined3d_stateblock_incref(ddraw->state);
+ wined3d_streaming_buffer_init(&device->vertex_buffer, WINED3D_BIND_VERTEX_BUFFER); + /* Render to the back buffer */ rtv = ddraw_surface_get_rendertarget_view(target); if (FAILED(hr = wined3d_device_context_set_rendertarget_views(device->immediate_context, 0, 1, &rtv, TRUE)))
From: Anton Baskanov baskanov@gmail.com
--- dlls/ddraw/ddraw_private.h | 6 +- dlls/ddraw/device.c | 110 ++++--------------------------------- 2 files changed, 12 insertions(+), 104 deletions(-)
diff --git a/dlls/ddraw/ddraw_private.h b/dlls/ddraw/ddraw_private.h index d2b1fc495fc..6693a650394 100644 --- a/dlls/ddraw/ddraw_private.h +++ b/dlls/ddraw/ddraw_private.h @@ -335,11 +335,7 @@ struct d3d_device struct ddraw *ddraw; IUnknown *rt_iface;
- struct wined3d_buffer *index_buffer; - UINT index_buffer_size; - UINT index_buffer_pos; - - struct wined3d_streaming_buffer vertex_buffer; + struct wined3d_streaming_buffer vertex_buffer, index_buffer;
/* Viewport management */ struct list viewport_list; diff --git a/dlls/ddraw/device.c b/dlls/ddraw/device.c index 9049f843ab0..c795a766769 100644 --- a/dlls/ddraw/device.c +++ b/dlls/ddraw/device.c @@ -279,8 +279,7 @@ static ULONG WINAPI d3d_device_inner_Release(IUnknown *iface) /* There is no need to unset any resources here, wined3d will take * care of that on uninit_3d(). */
- if (This->index_buffer) - wined3d_buffer_decref(This->index_buffer); + wined3d_streaming_buffer_cleanup(&This->index_buffer); wined3d_streaming_buffer_cleanup(&This->vertex_buffer);
wined3d_device_context_set_rendertarget_views(This->immediate_context, 0, 1, &null_rtv, FALSE); @@ -3569,42 +3568,6 @@ static HRESULT WINAPI d3d_device2_DrawPrimitive(IDirect3DDevice2 *iface, * DDERR_INVALIDPARAMS if Vertices or Indices is NULL * *****************************************************************************/ -/* The caller is responsible for wined3d locking */ -static HRESULT d3d_device_prepare_index_buffer(struct d3d_device *device, UINT min_size) -{ - HRESULT hr; - - if (device->index_buffer_size < min_size || !device->index_buffer) - { - UINT size = max(device->index_buffer_size * 2, min_size); - struct wined3d_buffer_desc desc; - struct wined3d_buffer *buffer; - - TRACE("Growing index buffer to %u bytes\n", size); - - desc.byte_width = size; - desc.usage = WINED3DUSAGE_DYNAMIC | WINED3DUSAGE_STATICDECL; - desc.bind_flags = WINED3D_BIND_INDEX_BUFFER; - desc.access = WINED3D_RESOURCE_ACCESS_GPU | WINED3D_RESOURCE_ACCESS_MAP_W; - desc.misc_flags = 0; - desc.structure_byte_stride = 0; - - if (FAILED(hr = wined3d_buffer_create(device->wined3d_device, &desc, - NULL, NULL, &ddraw_null_wined3d_parent_ops, &buffer))) - { - ERR("Failed to create index buffer, hr %#lx.\n", hr); - return hr; - } - - if (device->index_buffer) - wined3d_buffer_decref(device->index_buffer); - device->index_buffer = buffer; - device->index_buffer_size = size; - device->index_buffer_pos = 0; - } - return D3D_OK; -} - static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, D3DPRIMITIVETYPE primitive_type, DWORD fvf, void *vertices, DWORD vertex_count, WORD *indices, DWORD index_count, DWORD flags) @@ -3613,9 +3576,6 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, HRESULT hr; UINT stride = get_flexible_vertex_size(fvf); UINT vtx_size = stride * vertex_count, idx_size = index_count * sizeof(*indices); - struct wined3d_map_desc wined3d_map_desc; - struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *ib; UINT vb_pos, ib_pos;
TRACE("iface %p, primitive_type %#x, fvf %#lx, vertices %p, vertex_count %lu, " @@ -3635,27 +3595,14 @@ static HRESULT d3d_device7_DrawIndexedPrimitive(IDirect3DDevice7 *iface, &device->vertex_buffer, vertices, vtx_size, stride, &vb_pos))) goto done;
- hr = d3d_device_prepare_index_buffer(device, idx_size); - if (FAILED(hr)) - goto done; - ib_pos = device->index_buffer_pos; - if (device->index_buffer_size - idx_size < ib_pos) - ib_pos = 0; - - wined3d_box.left = ib_pos; - wined3d_box.right = ib_pos + idx_size; - ib = wined3d_buffer_get_resource(device->index_buffer); - if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device, + &device->index_buffer, indices, idx_size, sizeof(*indices), &ib_pos))) goto done; - memcpy(wined3d_map_desc.data, indices, idx_size); - wined3d_resource_unmap(ib, 0); - device->index_buffer_pos = ib_pos + idx_size;
hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, stride); if (FAILED(hr)) goto done; - wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT); + wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf)); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -3984,9 +3931,6 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, struct d3d_device *device = impl_from_IDirect3DDevice7(iface); UINT vtx_dst_stride = get_flexible_vertex_size(fvf); UINT idx_size = index_count * sizeof(WORD); - struct wined3d_map_desc wined3d_map_desc; - struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *ib; UINT vb_pos; UINT ib_pos; HRESULT hr; @@ -4009,27 +3953,14 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveStrided(IDirect3DDevice7 *iface, vertex_count, vtx_dst_stride, &vb_pos))) goto done;
- hr = d3d_device_prepare_index_buffer(device, idx_size); - if (FAILED(hr)) - goto done; - ib_pos = device->index_buffer_pos; - if (device->index_buffer_size - idx_size < ib_pos) - ib_pos = 0; - - wined3d_box.left = ib_pos; - wined3d_box.right = ib_pos + idx_size; - ib = wined3d_buffer_get_resource(device->index_buffer); - if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device, + &device->index_buffer, indices, idx_size, sizeof(WORD), &ib_pos))) goto done; - memcpy(wined3d_map_desc.data, indices, idx_size); - wined3d_resource_unmap(ib, 0); - device->index_buffer_pos = ib_pos + idx_size;
hr = wined3d_stateblock_set_stream_source(device->state, 0, device->vertex_buffer.buffer, 0, vtx_dst_stride); if (FAILED(hr)) goto done; - wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT); + wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
wined3d_stateblock_set_vertex_declaration(device->state, ddraw_find_decl(device->ddraw, fvf)); wined3d_device_context_set_primitive_type(device->immediate_context, @@ -4231,7 +4162,6 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface, struct wined3d_resource *wined3d_resource; struct wined3d_map_desc wined3d_map_desc; struct wined3d_box wined3d_box = {0}; - struct wined3d_resource *ib; HRESULT hr; UINT ib_pos;
@@ -4278,34 +4208,15 @@ static HRESULT d3d_device7_DrawIndexedPrimitiveVB(IDirect3DDevice7 *iface,
wined3d_stateblock_set_vertex_declaration(device->state, vb_impl->wined3d_declaration);
- hr = d3d_device_prepare_index_buffer(device, index_count * sizeof(WORD)); - if (FAILED(hr)) - { - wined3d_mutex_unlock(); - return hr; - } - ib_pos = device->index_buffer_pos; - - if (device->index_buffer_size - index_count * sizeof(WORD) < ib_pos) - ib_pos = 0; - - /* Copy the index stream into the index buffer. */ - wined3d_box.left = ib_pos; - wined3d_box.right = ib_pos + index_count * sizeof(WORD); - ib = wined3d_buffer_get_resource(device->index_buffer); - if (FAILED(hr = wined3d_resource_map(ib, 0, &wined3d_map_desc, &wined3d_box, - WINED3D_MAP_WRITE | (ib_pos ? WINED3D_MAP_NOOVERWRITE : WINED3D_MAP_DISCARD)))) + if (FAILED(hr = wined3d_streaming_buffer_upload(device->wined3d_device, + &device->index_buffer, indices, index_count * sizeof(WORD), sizeof(WORD), &ib_pos))) { - ERR("Failed to map buffer, hr %#lx.\n", hr); wined3d_mutex_unlock(); return hr; } - memcpy(wined3d_map_desc.data, indices, index_count * sizeof(WORD)); - wined3d_resource_unmap(ib, 0); - device->index_buffer_pos = ib_pos + index_count * sizeof(WORD);
/* Set the index stream */ - wined3d_stateblock_set_index_buffer(device->state, device->index_buffer, WINED3DFMT_R16_UINT); + wined3d_stateblock_set_index_buffer(device->state, device->index_buffer.buffer, WINED3DFMT_R16_UINT);
/* Set the vertex stream source */ if (FAILED(hr = wined3d_stateblock_set_stream_source(device->state, @@ -6884,6 +6795,7 @@ static HRESULT d3d_device_init(struct d3d_device *device, struct ddraw *ddraw, c wined3d_stateblock_incref(ddraw->state);
wined3d_streaming_buffer_init(&device->vertex_buffer, WINED3D_BIND_VERTEX_BUFFER); + wined3d_streaming_buffer_init(&device->index_buffer, WINED3D_BIND_INDEX_BUFFER);
/* Render to the back buffer */ rtv = ddraw_surface_get_rendertarget_view(target);
From: Anton Baskanov baskanov@gmail.com
Apps that issues many small draw calls (e.g. Earth 2150) may cause frequent DISCARD maps, which are significantly slower than NOOVERWRITE ones. --- dlls/wined3d/buffer.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index babbd0d0968..d2e9e92b14f 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -34,6 +34,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); #define VB_MAXFULLCONVERSIONS 5 /* Number of full conversions before we stop converting */ #define VB_RESETFULLCONVS 20 /* Reset full conversion counts after that number of draws */
+#define SB_MIN_SIZE (512 * 1024) /* Minimum size of an allocated streaming buffer. */ + struct wined3d_buffer_ops { BOOL (*buffer_prepare_location)(struct wined3d_buffer *buffer, @@ -1665,7 +1667,7 @@ static HRESULT wined3d_streaming_buffer_prepare(struct wined3d_device *device, return S_OK; }
- size = max(old_size * 2, min_size); + size = max(SB_MIN_SIZE, max(old_size * 2, min_size)); TRACE("Growing buffer to %u bytes.\n", size);
desc.byte_width = size;
I had a cursory look at this, and broadly it seems fine. I don't like the introduction of wined3d_draw_primitive_strided_data though, and think it could easily be avoided by exposing wined3d_streaming_buffer_map()/wined3d_streaming_buffer_unmap() instead.