d3d8: Filter out redundant buffer discards.

I was unable to write tests for this; it seems it doesn't consistently work on
Windows. However, Rayman 3 seems to rely on it; it maps the same buffer twice
immediately after creation, with DISCARD flags on both maps, and expects the
same address to be returned.

Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53752
This commit is contained in:
Zebediah Figura 2022-12-22 12:33:15 -06:00 committed by Alexandre Julliard
parent c96d34e86e
commit 379ae701c0
3 changed files with 38 additions and 2 deletions

View file

@ -192,6 +192,11 @@ static HRESULT WINAPI d3d8_vertexbuffer_Lock(IDirect3DVertexBuffer8 *iface, UINT
TRACE("iface %p, offset %u, size %u, data %p, flags %#lx.\n",
iface, offset, size, data, flags);
if (buffer->discarded)
flags &= ~D3DLOCK_DISCARD;
if (flags & D3DLOCK_DISCARD)
buffer->discarded = true;
wined3d_box.left = offset;
wined3d_box.right = offset + size;
wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);
@ -508,6 +513,11 @@ static HRESULT WINAPI d3d8_indexbuffer_Lock(IDirect3DIndexBuffer8 *iface, UINT o
TRACE("iface %p, offset %u, size %u, data %p, flags %#lx.\n",
iface, offset, size, data, flags);
if (buffer->discarded)
flags &= ~D3DLOCK_DISCARD;
if (flags & D3DLOCK_DISCARD)
buffer->discarded = true;
wined3d_box.left = offset;
wined3d_box.right = offset + size;
wined3d_resource = wined3d_buffer_get_resource(buffer->wined3d_buffer);

View file

@ -217,6 +217,7 @@ struct d3d8_vertexbuffer
IDirect3DDevice8 *parent_device;
struct wined3d_buffer *draw_buffer;
DWORD fvf, usage;
bool discarded;
};
HRESULT vertexbuffer_init(struct d3d8_vertexbuffer *buffer, struct d3d8_device *device,
@ -232,6 +233,7 @@ struct d3d8_indexbuffer
enum wined3d_format_id format;
DWORD usage;
bool sysmem;
bool discarded;
};
HRESULT indexbuffer_init(struct d3d8_indexbuffer *buffer, struct d3d8_device *device,

View file

@ -2516,7 +2516,8 @@ 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;
struct d3d8_vertexbuffer *vb;
unsigned int vertex_count, i;
TRACE("iface %p, primitive_type %#x, start_vertex %u, primitive_count %u.\n",
iface, primitive_type, start_vertex, primitive_count);
@ -2529,6 +2530,16 @@ static HRESULT WINAPI d3d8_device_DrawPrimitive(IDirect3DDevice8 *iface,
wined3d_primitive_type_from_d3d(primitive_type), 0);
wined3d_device_apply_stateblock(device->wined3d_device, device->state);
wined3d_device_context_draw(device->immediate_context, start_vertex, vertex_count, 0, 0);
for (i = 0; i < ARRAY_SIZE(device->stateblock_state->streams); ++i)
{
if (device->stateblock_state->streams[i].buffer)
{
vb = wined3d_buffer_get_parent(device->stateblock_state->streams[i].buffer);
vb->discarded = false;
}
}
wined3d_mutex_unlock();
return D3D_OK;
@ -2539,7 +2550,9 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
UINT start_idx, UINT primitive_count)
{
struct d3d8_device *device = impl_from_IDirect3DDevice8(iface);
unsigned int index_count;
struct d3d8_vertexbuffer *vb;
struct d3d8_indexbuffer *ib;
unsigned int index_count, i;
int base_vertex_index;
HRESULT hr;
@ -2567,6 +2580,17 @@ static HRESULT WINAPI d3d8_device_DrawIndexedPrimitive(IDirect3DDevice8 *iface,
}
wined3d_device_context_draw_indexed(device->immediate_context, base_vertex_index, start_idx, index_count, 0, 0);
ib = wined3d_buffer_get_parent(device->stateblock_state->index_buffer);
ib->discarded = false;
for (i = 0; i < ARRAY_SIZE(device->stateblock_state->streams); ++i)
{
if (device->stateblock_state->streams[i].buffer)
{
vb = wined3d_buffer_get_parent(device->stateblock_state->streams[i].buffer);
vb->discarded = false;
}
}
wined3d_mutex_unlock();
return D3D_OK;