Signed-off-by: Zebediah Figura zfigura@codeweavers.com --- The validation of offset (and, in patch 4/6, bind flags) is awkward, but I don't see a nice way to do it without changing the current behaviour.
dlls/d3d11/device.c | 49 +++++++++++++++++---------- dlls/wined3d/cs.c | 53 ++++++++++++++++------------- dlls/wined3d/device.c | 62 ++++++++++++++++++---------------- dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 4 +-- include/wine/wined3d.h | 4 +-- 6 files changed, 98 insertions(+), 76 deletions(-)
diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index 20f0c27d020..12675826394 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -841,26 +841,32 @@ static void STDMETHODCALLTYPE d3d11_device_context_IASetInputLayout(ID3D11Device static void STDMETHODCALLTYPE d3d11_device_context_IASetVertexBuffers(ID3D11DeviceContext1 *iface, UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers, const UINT *strides, const UINT *offsets) { + struct wined3d_stream_state streams[D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); unsigned int i;
TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, strides %p, offsets %p.\n", iface, start_slot, buffer_count, buffers, strides, offsets);
- wined3d_mutex_lock(); + if (buffer_count > ARRAY_SIZE(streams)) + { + WARN("Buffer count %u exceeds limit.\n", buffer_count); + buffer_count = ARRAY_SIZE(streams); + } + for (i = 0; i < buffer_count; ++i) { struct d3d_buffer *buffer = unsafe_impl_from_ID3D11Buffer(buffers[i]); - struct wined3d_stream_state stream;
- stream.buffer = buffer ? buffer->wined3d_buffer : NULL; - stream.offset = offsets[i]; - stream.stride = strides[i]; - stream.frequency = 1; - stream.flags = 0; - - wined3d_device_context_set_stream_source(context->wined3d_context, start_slot + i, &stream); + streams[i].buffer = buffer ? buffer->wined3d_buffer : NULL; + streams[i].offset = offsets[i]; + streams[i].stride = strides[i]; + streams[i].frequency = 1; + streams[i].flags = 0; } + + wined3d_mutex_lock(); + wined3d_device_context_set_stream_sources(context->wined3d_context, start_slot, buffer_count, streams); wined3d_mutex_unlock(); }
@@ -4701,26 +4707,33 @@ static void STDMETHODCALLTYPE d3d10_device_IASetInputLayout(ID3D10Device1 *iface static void STDMETHODCALLTYPE d3d10_device_IASetVertexBuffers(ID3D10Device1 *iface, UINT start_slot, UINT buffer_count, ID3D10Buffer *const *buffers, const UINT *strides, const UINT *offsets) { + struct wined3d_stream_state streams[D3D10_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT]; struct d3d_device *device = impl_from_ID3D10Device(iface); unsigned int i;
TRACE("iface %p, start_slot %u, buffer_count %u, buffers %p, strides %p, offsets %p\n", iface, start_slot, buffer_count, buffers, strides, offsets);
- wined3d_mutex_lock(); + if (buffer_count > ARRAY_SIZE(streams)) + { + WARN("Buffer count %u exceeds limit.\n", buffer_count); + buffer_count = ARRAY_SIZE(streams); + } + for (i = 0; i < buffer_count; ++i) { struct d3d_buffer *buffer = unsafe_impl_from_ID3D10Buffer(buffers[i]); - struct wined3d_stream_state stream;
- stream.buffer = buffer ? buffer->wined3d_buffer : NULL; - stream.offset = offsets[i]; - stream.stride = strides[i]; - stream.frequency = 1; - stream.flags = 0; - - wined3d_device_context_set_stream_source(device->immediate_context.wined3d_context, start_slot + i, &stream); + streams[i].buffer = buffer ? buffer->wined3d_buffer : NULL; + streams[i].offset = offsets[i]; + streams[i].stride = strides[i]; + streams[i].frequency = 1; + streams[i].flags = 0; } + + wined3d_mutex_lock(); + wined3d_device_context_set_stream_sources(device->immediate_context.wined3d_context, + start_slot, buffer_count, streams); wined3d_mutex_unlock(); }
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index 1cffd66d89a..c2ba4010704 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -116,7 +116,7 @@ enum wined3d_cs_op WINED3D_CS_OP_SET_RENDERTARGET_VIEW, WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW, WINED3D_CS_OP_SET_VERTEX_DECLARATION, - WINED3D_CS_OP_SET_STREAM_SOURCE, + WINED3D_CS_OP_SET_STREAM_SOURCES, WINED3D_CS_OP_SET_STREAM_OUTPUTS, WINED3D_CS_OP_SET_INDEX_BUFFER, WINED3D_CS_OP_SET_CONSTANT_BUFFERS, @@ -251,11 +251,12 @@ struct wined3d_cs_set_vertex_declaration struct wined3d_vertex_declaration *declaration; };
-struct wined3d_cs_set_stream_source +struct wined3d_cs_set_stream_sources { enum wined3d_cs_op opcode; - UINT stream_idx; - struct wined3d_stream_state state; + unsigned int start_idx; + unsigned int count; + struct wined3d_stream_state streams[1]; };
struct wined3d_cs_set_stream_outputs @@ -588,7 +589,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op) WINED3D_TO_STR(WINED3D_CS_OP_SET_RENDERTARGET_VIEW); WINED3D_TO_STR(WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW); WINED3D_TO_STR(WINED3D_CS_OP_SET_VERTEX_DECLARATION); - WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCE); + WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCES); WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_OUTPUTS); WINED3D_TO_STR(WINED3D_CS_OP_SET_INDEX_BUFFER); WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFERS); @@ -1397,33 +1398,37 @@ void wined3d_device_context_emit_set_vertex_declaration(struct wined3d_device_co wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); }
-static void wined3d_cs_exec_set_stream_source(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_stream_sources(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_stream_source *op = data; - struct wined3d_stream_state *stream; - struct wined3d_buffer *prev; + const struct wined3d_cs_set_stream_sources *op = data; + unsigned int i;
- stream = &cs->state.streams[op->stream_idx]; - prev = stream->buffer; - *stream = op->state; + for (i = 0; i < op->count; ++i) + { + struct wined3d_buffer *prev = cs->state.streams[op->start_idx + i].buffer; + struct wined3d_buffer *buffer = op->streams[i].buffer;
- if (op->state.buffer) - InterlockedIncrement(&op->state.buffer->resource.bind_count); - if (prev) - InterlockedDecrement(&prev->resource.bind_count); + if (buffer) + InterlockedIncrement(&buffer->resource.bind_count); + if (prev) + InterlockedDecrement(&prev->resource.bind_count); + }
+ memcpy(&cs->state.streams[op->start_idx], op->streams, op->count * sizeof(*op->streams)); device_invalidate_state(cs->c.device, STATE_STREAMSRC); }
-void wined3d_device_context_emit_set_stream_source(struct wined3d_device_context *context, unsigned int stream_idx, - const struct wined3d_stream_state *state) +void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context *context, + unsigned int start_idx, unsigned int count, const struct wined3d_stream_state *streams) { - struct wined3d_cs_set_stream_source *op; + struct wined3d_cs_set_stream_sources *op;
- op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); - op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCE; - op->stream_idx = stream_idx; - op->state = *state; + op = wined3d_device_context_require_space(context, + offsetof(struct wined3d_cs_set_stream_sources, streams[count]), WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_STREAM_SOURCES; + op->start_idx = start_idx; + op->count = count; + memcpy(op->streams, streams, count * sizeof(*streams));
wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); } @@ -2882,7 +2887,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_SET_RENDERTARGET_VIEW */ wined3d_cs_exec_set_rendertarget_view, /* WINED3D_CS_OP_SET_DEPTH_STENCIL_VIEW */ wined3d_cs_exec_set_depth_stencil_view, /* WINED3D_CS_OP_SET_VERTEX_DECLARATION */ wined3d_cs_exec_set_vertex_declaration, - /* WINED3D_CS_OP_SET_STREAM_SOURCE */ wined3d_cs_exec_set_stream_source, + /* WINED3D_CS_OP_SET_STREAM_SOURCES */ wined3d_cs_exec_set_stream_sources, /* WINED3D_CS_OP_SET_STREAM_OUTPUTS */ wined3d_cs_exec_set_stream_outputs, /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index c8e81e923cc..84bda7b44d9 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1661,8 +1661,7 @@ void CDECL wined3d_device_context_set_state(struct wined3d_device_context *conte
wined3d_device_context_emit_set_stream_outputs(context, state->stream_output);
- for (i = 0; i < WINED3D_MAX_STREAMS; ++i) - wined3d_device_context_emit_set_stream_source(context, i, &state->streams[i]); + wined3d_device_context_emit_set_stream_sources(context, 0, WINED3D_MAX_STREAMS, state->streams);
wined3d_device_context_emit_set_index_buffer(context, state->index_buffer, state->index_format, state->index_offset); @@ -2219,43 +2218,48 @@ void CDECL wined3d_device_context_set_predication(struct wined3d_device_context wined3d_query_decref(prev); }
-HRESULT CDECL wined3d_device_context_set_stream_source(struct wined3d_device_context *context, - unsigned int stream_idx, const struct wined3d_stream_state *src_stream) +HRESULT CDECL wined3d_device_context_set_stream_sources(struct wined3d_device_context *context, + unsigned int start_idx, unsigned int count, const struct wined3d_stream_state *streams) { - struct wined3d_buffer *buffer = src_stream->buffer; - struct wined3d_stream_state *dst_stream; - struct wined3d_buffer *prev_buffer; + struct wined3d_state *state = context->state; + HRESULT hr = WINED3D_OK; + unsigned int i;
- TRACE("context %p, stream_idx %u, src_stream %p.\n", context, stream_idx, src_stream); + TRACE("context %p, start_idx %u, count %u, streams %p.\n", context, start_idx, count, streams);
- if (stream_idx >= WINED3D_MAX_STREAMS) + if (start_idx >= WINED3D_MAX_STREAMS) { - WARN("Stream index %u out of range.\n", stream_idx); - return WINED3DERR_INVALIDCALL; - } - else if (src_stream->offset & 0x3) - { - WARN("Offset %u is not 4 byte aligned.\n", src_stream->offset); + WARN("Start index %u is out of range.\n", start_idx); return WINED3DERR_INVALIDCALL; }
- dst_stream = &context->state->streams[stream_idx]; - prev_buffer = dst_stream->buffer; + count = min(count, WINED3D_MAX_STREAMS - start_idx);
- if (!memcmp(src_stream, dst_stream, sizeof(*src_stream))) - { - TRACE("Application is setting the old values over, nothing to do.\n"); + if (!memcmp(streams, &state->streams[start_idx], count * sizeof(*streams))) return WINED3D_OK; + + wined3d_device_context_emit_set_stream_sources(context, start_idx, count, streams); + for (i = 0; i < count; ++i) + { + struct wined3d_buffer *prev = state->streams[start_idx + i].buffer; + struct wined3d_buffer *buffer = streams[i].buffer; + + if (streams[i].offset & 0x3) + { + WARN("Offset %u is not 4 byte aligned.\n", streams[i].offset); + hr = WINED3DERR_INVALIDCALL; + continue; + } + + state->streams[start_idx + i] = streams[i]; + + if (buffer) + wined3d_buffer_incref(buffer); + if (prev) + wined3d_buffer_decref(prev); }
- *dst_stream = *src_stream; - if (buffer) - wined3d_buffer_incref(buffer); - wined3d_device_context_emit_set_stream_source(context, stream_idx, src_stream); - if (prev_buffer) - wined3d_buffer_decref(prev_buffer); - - return WINED3D_OK; + return hr; }
void CDECL wined3d_device_context_set_index_buffer(struct wined3d_device_context *context, @@ -3912,7 +3916,7 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device, while (map) { i = wined3d_bit_scan(&map); - wined3d_device_context_set_stream_source(context, i, &state->streams[i]); + wined3d_device_context_set_stream_sources(context, i, 1, &state->streams[i]); }
map = changed->textures; diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 1dac446a0e0..c6a61b98242 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -137,7 +137,7 @@ @ cdecl wined3d_device_context_set_shader_resource_views(ptr long long long ptr) @ cdecl wined3d_device_context_set_state(ptr ptr) @ cdecl wined3d_device_context_set_stream_outputs(ptr ptr) -@ cdecl wined3d_device_context_set_stream_source(ptr long ptr) +@ cdecl wined3d_device_context_set_stream_sources(ptr long long ptr) @ cdecl wined3d_device_context_set_unordered_access_views(ptr long long long ptr ptr) @ cdecl wined3d_device_context_set_vertex_declaration(ptr ptr) @ cdecl wined3d_device_context_set_viewports(ptr long ptr) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 98b387b73c0..19a19dced27 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4840,8 +4840,8 @@ void wined3d_device_context_emit_set_shader_resource_views(struct wined3d_device struct wined3d_shader_resource_view *const *views) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_stream_outputs(struct wined3d_device_context *context, const struct wined3d_stream_output outputs[WINED3D_MAX_STREAM_OUTPUT_BUFFERS]) DECLSPEC_HIDDEN; -void wined3d_device_context_emit_set_stream_source(struct wined3d_device_context *context, unsigned int stream_idx, - const struct wined3d_stream_state *state) DECLSPEC_HIDDEN; +void wined3d_device_context_emit_set_stream_sources(struct wined3d_device_context *context, + unsigned int start_idx, unsigned int count, const struct wined3d_stream_state *streams) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_texture(struct wined3d_device_context *context, unsigned int stage, struct wined3d_texture *texture) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_texture_state(struct wined3d_device_context *context, unsigned int stage, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 94bbb4061c4..6bfc755a5bb 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2531,8 +2531,8 @@ void __cdecl wined3d_device_context_set_shader_resource_views(struct wined3d_dev void __cdecl wined3d_device_context_set_state(struct wined3d_device_context *context, struct wined3d_state *state); void __cdecl wined3d_device_context_set_stream_outputs(struct wined3d_device_context *context, const struct wined3d_stream_output outputs[WINED3D_MAX_STREAM_OUTPUT_BUFFERS]); -HRESULT __cdecl wined3d_device_context_set_stream_source(struct wined3d_device_context *context, - unsigned int stream_idx, const struct wined3d_stream_state *stream); +HRESULT __cdecl wined3d_device_context_set_stream_sources(struct wined3d_device_context *context, + unsigned int start_idx, unsigned int count, const struct wined3d_stream_state *streams); void __cdecl wined3d_device_context_set_unordered_access_views(struct wined3d_device_context *context, enum wined3d_pipeline pipeline, unsigned int start_idx, unsigned int count, struct wined3d_unordered_access_view *const *uavs, const unsigned int *initial_counts);