[PATCH v2 1/5] wined3d: Set an array of constant buffers as a single CS operation.

Zebediah Figura zfigura at codeweavers.com
Mon Jul 5 21:40:52 CDT 2021


Signed-off-by: Zebediah Figura <zfigura at codeweavers.com>
---
 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 ce0417c9f71..05adb32ae64 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);
 }
@@ -2903,7 +2912,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 5a2a95ebe96..e123afea96d 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 80e03ad9212..f03c7130c53 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4809,8 +4809,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,
-- 
2.30.2




More information about the wine-devel mailing list