From bbd02a077bf5ba977724ada68709f46150e482fb Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Tue, 20 Aug 2013 15:12:26 +0200
Subject: wined3d: Send float constant updates through the command stream

---
 dlls/wined3d/cs.c              | 88 ++++++++++++++++++++++++++++++++----------
 dlls/wined3d/device.c          |  7 ++--
 dlls/wined3d/wined3d_private.h |  2 +
 3 files changed, 74 insertions(+), 23 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index d252773..56cbcb6 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -63,6 +63,8 @@ enum wined3d_cs_op
     WINED3D_CS_OP_SET_MATERIAL,
     WINED3D_CS_OP_RESET_STATE,
     WINED3D_CS_OP_STATEBLOCK,
+    WINED3D_CS_OP_SET_VS_CONSTS_F,
+    WINED3D_CS_OP_SET_PS_CONSTS_F,
     WINED3D_CS_OP_STOP,
 };
 
@@ -273,7 +275,13 @@ struct wined3d_cs_stateblock
 {
     enum wined3d_cs_op opcode;
     struct wined3d_state state;
-    float vs_consts_f[256 * 4], ps_consts_f[256 * 4];
+};
+
+struct wined3d_cs_set_consts_f
+{
+    enum wined3d_cs_op opcode;
+    UINT start_register, vector4f_count;
+    float constants[4];
 };
 
 /* FIXME: The list synchronization probably isn't particularly fast. */
@@ -910,13 +918,7 @@ void wined3d_cs_emit_set_texture(struct wined3d_cs *cs, UINT stage, struct wined
 
 static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const void *data)
 {
-    const struct wined3d_adapter *adapter = cs->device->adapter;
     const struct wined3d_cs_stateblock *op = data;
-    UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4;
-    UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4;
-
-    num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count);
-    num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count);
 
     /* Don't memcpy the entire struct, we'll remove single items as we add dedicated
      * ops for setting states */
@@ -927,11 +929,9 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi
 
     memcpy(cs->state.vs_consts_b, op->state.vs_consts_b, sizeof(cs->state.vs_consts_b));
     memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i));
-    memcpy(cs->state.vs_consts_f, op->state.vs_consts_f, sizeof(*cs->state.vs_consts_f) * num_vs_consts_f);
 
     memcpy(cs->state.ps_consts_b, op->state.ps_consts_b, sizeof(cs->state.ps_consts_b));
     memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i));
-    memcpy(cs->state.ps_consts_f, op->state.ps_consts_f, sizeof(*cs->state.ps_consts_f) * num_ps_consts_f);
 
     memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights));
 
@@ -940,14 +940,7 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi
 
 void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct wined3d_state *state)
 {
-    const struct wined3d_device *device = cs->device;
-    const struct wined3d_adapter *adapter = device->adapter;
     struct wined3d_cs_stateblock *op;
-    UINT num_vs_consts_f = sizeof(op->vs_consts_f) / sizeof(*op->vs_consts_f) / 4;
-    UINT num_ps_consts_f = sizeof(op->ps_consts_f) / sizeof(*op->ps_consts_f) / 4;
-
-    num_vs_consts_f = min(num_vs_consts_f, adapter->d3d_info.limits.vs_uniform_count);
-    num_ps_consts_f = min(num_ps_consts_f, adapter->d3d_info.limits.ps_uniform_count);
 
     op = cs->ops->require_space(cs, sizeof(*op));
     op->opcode = WINED3D_CS_OP_STATEBLOCK;
@@ -960,13 +953,9 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win
 
     memcpy(op->state.vs_consts_b, state->vs_consts_b, sizeof(op->state.vs_consts_b));
     memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i));
-    op->state.vs_consts_f = op->vs_consts_f;
-    memcpy(op->state.vs_consts_f, state->vs_consts_f, sizeof(*op->state.vs_consts_f) * num_vs_consts_f);
 
     memcpy(op->state.ps_consts_b, state->ps_consts_b, sizeof(op->state.ps_consts_b));
     memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i));
-    op->state.ps_consts_f = op->ps_consts_f;
-    memcpy(op->state.ps_consts_f, state->ps_consts_f, sizeof(*op->state.ps_consts_f) * num_ps_consts_f);
 
     /* FIXME: This is not ideal. CS is still running synchronously, so this is ok.
      * It will go away soon anyway. */
@@ -1039,6 +1028,63 @@ void wined3d_cs_emit_set_shader(struct wined3d_cs *cs, enum wined3d_shader_type
     op->opcode = WINED3D_CS_OP_SET_SHADER;
     op->type = type;
     op->shader = shader;
+}
+
+static UINT wined3d_cs_exec_set_vs_consts_f(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_f *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(cs->state.vs_consts_f + op->start_register * 4, op->constants,
+            sizeof(*cs->state.vs_consts_f) * 4 * op->vector4f_count);
+
+    device->shader_backend->shader_update_float_vertex_constants(device,
+            op->start_register, op->vector4f_count);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->vector4f_count - 1);
+}
+
+static UINT wined3d_cs_exec_set_ps_consts_f(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_f *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(cs->state.ps_consts_f + op->start_register * 4, op->constants,
+            sizeof(*cs->state.ps_consts_f) * 4 * op->vector4f_count);
+
+    device->shader_backend->shader_update_float_pixel_constants(device,
+            op->start_register, op->vector4f_count);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->vector4f_count - 1);
+}
+
+void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register,
+        const float *constants, UINT vector4f_count, enum wined3d_shader_type type)
+{
+    struct wined3d_cs_set_consts_f *op;
+    UINT extra_space = vector4f_count - 1;
+
+    op = cs->ops->require_space(cs, sizeof(*op) + sizeof(op->constants) * extra_space);
+    switch (type)
+    {
+        case WINED3D_SHADER_TYPE_PIXEL:
+            op->opcode = WINED3D_CS_OP_SET_PS_CONSTS_F;
+            break;
+
+        case WINED3D_SHADER_TYPE_VERTEX:
+            op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_F;
+            break;
+
+        case WINED3D_SHADER_TYPE_GEOMETRY:
+            FIXME("Invalid for geometry shaders\n");
+            return;
+
+        case WINED3D_SHADER_TYPE_COUNT:
+            break;
+    }
+    op->start_register = start_register;
+    op->vector4f_count = vector4f_count;
+    memcpy(op->constants, constants, sizeof(*constants) * 4 * vector4f_count);
 
     cs->ops->submit(cs);
 }
@@ -1233,6 +1279,8 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_SET_MATERIAL               */ wined3d_cs_exec_set_material,
     /* WINED3D_CS_OP_RESET_STATE                */ wined3d_cs_exec_reset_state,
     /* WINED3D_CS_OP_STATEBLOCK                 */ wined3d_cs_exec_transfer_stateblock,
+    /* WINED3D_CS_OP_SET_VS_CONSTS_F            */ wined3d_cs_exec_set_vs_consts_f,
+    /* WINED3D_CS_OP_SET_PS_CONSTS_F            */ wined3d_cs_exec_set_ps_consts_f,
 };
 
 static void *wined3d_cs_st_require_space(struct wined3d_cs *cs, size_t size)
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 6ea0b9a..2aba2a4 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2341,8 +2341,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_f(struct wined3d_device *device,
         memset(device->recording->changed.vertexShaderConstantsF + start_register, 1,
                 sizeof(*device->recording->changed.vertexShaderConstantsF) * vector4f_count);
     else
-        device->shader_backend->shader_update_float_vertex_constants(device, start_register, vector4f_count);
-
+        wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count,
+                WINED3D_SHADER_TYPE_VERTEX);
 
     return WINED3D_OK;
 }
@@ -2576,7 +2576,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_f(struct wined3d_device *device,
         memset(device->recording->changed.pixelShaderConstantsF + start_register, 1,
                 sizeof(*device->recording->changed.pixelShaderConstantsF) * vector4f_count);
     else
-        device->shader_backend->shader_update_float_pixel_constants(device, start_register, vector4f_count);
+        wined3d_cs_emit_set_consts_f(device->cs, start_register, constants, vector4f_count,
+                WINED3D_SHADER_TYPE_PIXEL);
 
     return WINED3D_OK;
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 02104ce..d673a8f 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2613,6 +2613,8 @@ void wined3d_cs_emit_set_transform(struct wined3d_cs *cs, enum wined3d_transform
 void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
         struct wined3d_vertex_declaration *declaration) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_viewport(struct wined3d_cs *cs, const struct wined3d_viewport *viewport) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, const float *constants,
+        UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN;
 
 /* Direct3D terminology with little modifications. We do not have an issued state
  * because only the driver knows about it, but we have a created state because d3d
-- 
2.1.3

