From e6bbf6ee9151c632bfc9e73b785e51dcb001d0ad Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 5 Jul 2021 21:40:52 -0500 Subject: [PATCH] wined3d: Set an array of constant buffers as a single CS operation. Signed-off-by: Zebediah Figura Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- dlls/d3d11/device.c | 38 +++++++++++++++++------- dlls/wined3d/cs.c | 53 ++++++++++++++++++++-------------- dlls/wined3d/device.c | 37 ++++++++++++++---------- dlls/wined3d/wined3d.spec | 2 +- dlls/wined3d/wined3d_private.h | 5 ++-- include/wine/wined3d.h | 5 ++-- 6 files changed, 87 insertions(+), 53 deletions(-) diff --git a/dlls/d3d11/device.c b/dlls/d3d11/device.c index f8bd8578cdc..0385db9c138 100644 --- a/dlls/d3d11/device.c +++ b/dlls/d3d11/device.c @@ -560,20 +560,29 @@ static void d3d11_device_context_get_constant_buffers(ID3D11DeviceContext1 *ifac wined3d_mutex_unlock(); } -static void d3d11_device_context_set_constant_buffers(ID3D11DeviceContext1 *iface, - enum wined3d_shader_type type, UINT start_slot, UINT buffer_count, ID3D11Buffer *const *buffers) +static void d3d11_device_context_set_constant_buffers(ID3D11DeviceContext1 *iface, enum wined3d_shader_type type, + unsigned int start_slot, unsigned int buffer_count, ID3D11Buffer *const *buffers) { + struct wined3d_buffer *wined3d_buffers[D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; struct d3d11_device_context *context = impl_from_ID3D11DeviceContext1(iface); unsigned int i; - wined3d_mutex_lock(); + if (buffer_count > ARRAY_SIZE(wined3d_buffers)) + { + WARN("Buffer count %u exceeds limit; ignoring call.\n", buffer_count); + return; + } + for (i = 0; i < buffer_count; ++i) { struct d3d_buffer *buffer = unsafe_impl_from_ID3D11Buffer(buffers[i]); - wined3d_device_context_set_constant_buffer(context->wined3d_context, type, start_slot + i, - buffer ? buffer->wined3d_buffer : NULL); + wined3d_buffers[i] = buffer ? buffer->wined3d_buffer : NULL; } + + wined3d_mutex_lock(); + wined3d_device_context_set_constant_buffers(context->wined3d_context, + type, start_slot, buffer_count, wined3d_buffers); wined3d_mutex_unlock(); } @@ -4571,20 +4580,29 @@ static void d3d10_device_get_constant_buffers(ID3D10Device1 *iface, wined3d_mutex_unlock(); } -static void d3d10_device_set_constant_buffers(ID3D10Device1 *iface, - enum wined3d_shader_type type, UINT start_slot, UINT buffer_count, ID3D10Buffer *const *buffers) +static void d3d10_device_set_constant_buffers(ID3D10Device1 *iface, enum wined3d_shader_type type, + unsigned int start_slot, unsigned int buffer_count, ID3D10Buffer *const *buffers) { + struct wined3d_buffer *wined3d_buffers[D3D10_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT]; struct d3d_device *device = impl_from_ID3D10Device(iface); unsigned int i; - wined3d_mutex_lock(); + if (buffer_count > ARRAY_SIZE(wined3d_buffers)) + { + WARN("Buffer count %u exceeds limit; ignoring call.\n", buffer_count); + return; + } + for (i = 0; i < buffer_count; ++i) { struct d3d_buffer *buffer = unsafe_impl_from_ID3D10Buffer(buffers[i]); - wined3d_device_context_set_constant_buffer(device->immediate_context.wined3d_context, type, start_slot + i, - buffer ? buffer->wined3d_buffer : NULL); + wined3d_buffers[i] = buffer ? buffer->wined3d_buffer : NULL; } + + wined3d_mutex_lock(); + wined3d_device_context_set_constant_buffers(device->immediate_context.wined3d_context, + type, start_slot, buffer_count, wined3d_buffers); wined3d_mutex_unlock(); } diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c index b7c48d2d0a9..88ecaf2c9c0 100644 --- a/dlls/wined3d/cs.c +++ b/dlls/wined3d/cs.c @@ -120,7 +120,7 @@ enum wined3d_cs_op WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ, WINED3D_CS_OP_SET_STREAM_OUTPUT, WINED3D_CS_OP_SET_INDEX_BUFFER, - WINED3D_CS_OP_SET_CONSTANT_BUFFER, + WINED3D_CS_OP_SET_CONSTANT_BUFFERS, WINED3D_CS_OP_SET_TEXTURE, WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW, WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW, @@ -285,12 +285,13 @@ struct wined3d_cs_set_index_buffer unsigned int offset; }; -struct wined3d_cs_set_constant_buffer +struct wined3d_cs_set_constant_buffers { enum wined3d_cs_op opcode; enum wined3d_shader_type type; - UINT cb_idx; - struct wined3d_buffer *buffer; + unsigned int start_idx; + unsigned int count; + struct wined3d_buffer *buffers[1]; }; struct wined3d_cs_set_texture @@ -598,7 +599,7 @@ static const char *debug_cs_op(enum wined3d_cs_op op) WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ); WINED3D_TO_STR(WINED3D_CS_OP_SET_STREAM_OUTPUT); WINED3D_TO_STR(WINED3D_CS_OP_SET_INDEX_BUFFER); - WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFER); + WINED3D_TO_STR(WINED3D_CS_OP_SET_CONSTANT_BUFFERS); WINED3D_TO_STR(WINED3D_CS_OP_SET_TEXTURE); WINED3D_TO_STR(WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW); WINED3D_TO_STR(WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW); @@ -1529,32 +1530,40 @@ void wined3d_device_context_emit_set_index_buffer(struct wined3d_device_context wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); } -static void wined3d_cs_exec_set_constant_buffer(struct wined3d_cs *cs, const void *data) +static void wined3d_cs_exec_set_constant_buffers(struct wined3d_cs *cs, const void *data) { - const struct wined3d_cs_set_constant_buffer *op = data; - struct wined3d_buffer *prev; + const struct wined3d_cs_set_constant_buffers *op = data; + unsigned int i; - prev = cs->state.cb[op->type][op->cb_idx]; - cs->state.cb[op->type][op->cb_idx] = op->buffer; + for (i = 0; i < op->count; ++i) + { + struct wined3d_buffer *prev = cs->state.cb[op->type][op->start_idx + i]; + struct wined3d_buffer *buffer = op->buffers[i]; - if (op->buffer) - InterlockedIncrement(&op->buffer->resource.bind_count); - if (prev) - InterlockedDecrement(&prev->resource.bind_count); + cs->state.cb[op->type][op->start_idx + i] = buffer; + + if (buffer) + InterlockedIncrement(&buffer->resource.bind_count); + if (prev) + InterlockedDecrement(&prev->resource.bind_count); + } device_invalidate_state(cs->c.device, STATE_CONSTANT_BUFFER(op->type)); } -void wined3d_device_context_emit_set_constant_buffer(struct wined3d_device_context *context, - enum wined3d_shader_type type, UINT cb_idx, struct wined3d_buffer *buffer) +void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context *context, + enum wined3d_shader_type type, unsigned int start_idx, unsigned int count, + struct wined3d_buffer *const *buffers) { - struct wined3d_cs_set_constant_buffer *op; + struct wined3d_cs_set_constant_buffers *op; - op = wined3d_device_context_require_space(context, sizeof(*op), WINED3D_CS_QUEUE_DEFAULT); - op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFER; + op = wined3d_device_context_require_space(context, offsetof(struct wined3d_cs_set_constant_buffers, buffers[count]), + WINED3D_CS_QUEUE_DEFAULT); + op->opcode = WINED3D_CS_OP_SET_CONSTANT_BUFFERS; op->type = type; - op->cb_idx = cb_idx; - op->buffer = buffer; + op->start_idx = start_idx; + op->count = count; + memcpy(op->buffers, buffers, count * sizeof(*buffers)); wined3d_device_context_submit(context, WINED3D_CS_QUEUE_DEFAULT); } @@ -2890,7 +2899,7 @@ static void (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void /* WINED3D_CS_OP_SET_STREAM_SOURCE_FREQ */ wined3d_cs_exec_set_stream_source_freq, /* WINED3D_CS_OP_SET_STREAM_OUTPUT */ wined3d_cs_exec_set_stream_output, /* WINED3D_CS_OP_SET_INDEX_BUFFER */ wined3d_cs_exec_set_index_buffer, - /* WINED3D_CS_OP_SET_CONSTANT_BUFFER */ wined3d_cs_exec_set_constant_buffer, + /* WINED3D_CS_OP_SET_CONSTANT_BUFFERS */ wined3d_cs_exec_set_constant_buffers, /* WINED3D_CS_OP_SET_TEXTURE */ wined3d_cs_exec_set_texture, /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW */ wined3d_cs_exec_set_shader_resource_view, /* WINED3D_CS_OP_SET_UNORDERED_ACCESS_VIEW */ wined3d_cs_exec_set_unordered_access_view, diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c index b97d565c42d..47919ed4f2d 100644 --- a/dlls/wined3d/device.c +++ b/dlls/wined3d/device.c @@ -1696,8 +1696,7 @@ void CDECL wined3d_device_context_set_state(struct wined3d_device_context *conte for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i) { wined3d_device_context_emit_set_shader(context, i, state->shader[i]); - for (j = 0; j < MAX_CONSTANT_BUFFERS; ++j) - wined3d_device_context_emit_set_constant_buffer(context, i, j, state->cb[i][j]); + wined3d_device_context_emit_set_constant_buffers(context, i, 0, MAX_CONSTANT_BUFFERS, state->cb[i]); for (j = 0; j < MAX_SAMPLER_OBJECTS; ++j) { wined3d_device_context_emit_set_sampler(context, i, j, state->sampler[i][j]); @@ -1834,30 +1833,36 @@ struct wined3d_shader * CDECL wined3d_device_context_get_shader(const struct win return context->state->shader[type]; } -void CDECL wined3d_device_context_set_constant_buffer(struct wined3d_device_context *context, - enum wined3d_shader_type type, unsigned int idx, struct wined3d_buffer *buffer) +void CDECL wined3d_device_context_set_constant_buffers(struct wined3d_device_context *context, + enum wined3d_shader_type type, unsigned int start_idx, unsigned int count, + struct wined3d_buffer *const *buffers) { struct wined3d_state *state = context->state; - struct wined3d_buffer *prev; + unsigned int i; - TRACE("context %p, type %#x, idx %u, buffer %p.\n", context, type, idx, buffer); + TRACE("context %p, type %#x, start_idx %u, count %u, buffers %p.\n", context, type, start_idx, count, buffers); - if (idx >= MAX_CONSTANT_BUFFERS) + if (start_idx >= MAX_CONSTANT_BUFFERS || count > MAX_CONSTANT_BUFFERS - start_idx) { - WARN("Invalid constant buffer index %u.\n", idx); + WARN("Invalid constant buffer index %u, count %u.\n", start_idx, count); return; } - prev = state->cb[type][idx]; - if (buffer == prev) + if (!memcmp(buffers, &state->cb[type][start_idx], count * sizeof(*buffers))) return; - if (buffer) - wined3d_buffer_incref(buffer); - state->cb[type][idx] = buffer; - wined3d_device_context_emit_set_constant_buffer(context, type, idx, buffer); - if (prev) - wined3d_buffer_decref(prev); + wined3d_device_context_emit_set_constant_buffers(context, type, start_idx, count, buffers); + for (i = 0; i < count; ++i) + { + struct wined3d_buffer *prev = state->cb[type][start_idx + i]; + struct wined3d_buffer *buffer = buffers[i]; + + if (buffer) + wined3d_buffer_incref(buffer); + state->cb[type][start_idx + i] = buffer; + if (prev) + wined3d_buffer_decref(prev); + } } void CDECL wined3d_device_context_set_blend_state(struct wined3d_device_context *context, diff --git a/dlls/wined3d/wined3d.spec b/dlls/wined3d/wined3d.spec index 11351b60a7f..a3f7f4ba405 100644 --- a/dlls/wined3d/wined3d.spec +++ b/dlls/wined3d/wined3d.spec @@ -123,7 +123,7 @@ @ cdecl wined3d_device_context_reset_state(ptr) @ cdecl wined3d_device_context_resolve_sub_resource(ptr ptr long ptr long long) @ cdecl wined3d_device_context_set_blend_state(ptr ptr ptr long) -@ cdecl wined3d_device_context_set_constant_buffer(ptr long long ptr) +@ cdecl wined3d_device_context_set_constant_buffers(ptr long long long ptr) @ cdecl wined3d_device_context_set_depth_stencil_state(ptr ptr long) @ cdecl wined3d_device_context_set_depth_stencil_view(ptr ptr) @ cdecl wined3d_device_context_set_index_buffer(ptr ptr long long) diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 5f0c2bb6732..63a5ae14e9b 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4810,8 +4810,9 @@ void wined3d_device_context_emit_set_blend_state(struct wined3d_device_context * unsigned int sample_mask) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_clip_plane(struct wined3d_device_context *context, unsigned int plane_idx, const struct wined3d_vec4 *plane) DECLSPEC_HIDDEN; -void wined3d_device_context_emit_set_constant_buffer(struct wined3d_device_context *context, - enum wined3d_shader_type type, UINT cb_idx, struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; +void wined3d_device_context_emit_set_constant_buffers(struct wined3d_device_context *context, + enum wined3d_shader_type type, unsigned int start_idx, unsigned int count, + struct wined3d_buffer *const *buffers) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_depth_stencil_state(struct wined3d_device_context *context, struct wined3d_depth_stencil_state *state, unsigned int stencil_ref) DECLSPEC_HIDDEN; void wined3d_device_context_emit_set_depth_stencil_view(struct wined3d_device_context *context, diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h index 53ae13b7df5..8994a78e99f 100644 --- a/include/wine/wined3d.h +++ b/include/wine/wined3d.h @@ -2496,8 +2496,9 @@ void __cdecl wined3d_device_context_resolve_sub_resource(struct wined3d_device_c struct wined3d_resource *src_resource, unsigned int src_sub_resource_idx, enum wined3d_format_id format_id); void __cdecl wined3d_device_context_set_blend_state(struct wined3d_device_context *context, struct wined3d_blend_state *state, const struct wined3d_color *blend_factor, unsigned int sample_mask); -void __cdecl wined3d_device_context_set_constant_buffer(struct wined3d_device_context *context, - enum wined3d_shader_type type, unsigned int idx, struct wined3d_buffer *buffer); +void __cdecl wined3d_device_context_set_constant_buffers(struct wined3d_device_context *context, + enum wined3d_shader_type type, unsigned int start_idx, unsigned int count, + struct wined3d_buffer *const *buffers); void __cdecl wined3d_device_context_set_depth_stencil_state(struct wined3d_device_context *context, struct wined3d_depth_stencil_state *depth_stencil_state, unsigned int stencil_ref); HRESULT __cdecl wined3d_device_context_set_depth_stencil_view(struct wined3d_device_context *context,