From 68141ab2e84252e99bcf6801a5bcc629b1494665 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 10 Apr 2013 14:20:47 +0200
Subject: wined3d: Send int constant updates through the command stream

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

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 9d8491a..cf3a523 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -65,8 +65,10 @@ enum wined3d_cs_op
     WINED3D_CS_OP_STATEBLOCK,
     WINED3D_CS_OP_SET_VS_CONSTS_F,
     WINED3D_CS_OP_SET_VS_CONSTS_B,
+    WINED3D_CS_OP_SET_VS_CONSTS_I,
     WINED3D_CS_OP_SET_PS_CONSTS_F,
     WINED3D_CS_OP_SET_PS_CONSTS_B,
+    WINED3D_CS_OP_SET_PS_CONSTS_I,
     WINED3D_CS_OP_GLFINISH,
     WINED3D_CS_OP_SET_BASE_VERTEX_INDEX,
     WINED3D_CS_OP_SET_PRIMITIVE_TYPE,
@@ -296,6 +298,13 @@ struct wined3d_cs_set_consts_b
     BOOL constants[1];
 };
 
+struct wined3d_cs_set_consts_i
+{
+    enum wined3d_cs_op opcode;
+    UINT start_register, vector4i_count;
+    int constants[4];
+};
+
 struct wined3d_cs_finish
 {
     enum wined3d_cs_op opcode;
@@ -968,9 +977,6 @@ static UINT wined3d_cs_exec_transfer_stateblock(struct wined3d_cs *cs, const voi
 
     /* Don't memcpy the entire struct, we'll remove single items as we add dedicated
      * ops for setting states */
-    memcpy(cs->state.vs_consts_i, op->state.vs_consts_i, sizeof(cs->state.vs_consts_i));
-
-    memcpy(cs->state.ps_consts_i, op->state.ps_consts_i, sizeof(cs->state.ps_consts_i));
 
     memcpy(cs->state.lights, op->state.lights, sizeof(cs->state.lights));
 
@@ -986,9 +992,6 @@ void wined3d_cs_emit_transfer_stateblock(struct wined3d_cs *cs, const struct win
 
     /* Don't memcpy the entire struct, we'll remove single items as we add dedicated
      * ops for setting states */
-    memcpy(op->state.vs_consts_i, state->vs_consts_i, sizeof(op->state.vs_consts_i));
-
-    memcpy(op->state.ps_consts_i, state->ps_consts_i, sizeof(op->state.ps_consts_i));
 
     /* FIXME: This is not ideal. CS is still running synchronously, so this is ok.
      * It will go away soon anyway. */
@@ -1201,6 +1204,63 @@ void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register,
     cs->ops->submit(cs);
 }
 
+static UINT wined3d_cs_exec_set_vs_consts_i(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_i *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(&cs->state.vs_consts_i[op->start_register * 4], op->constants,
+            sizeof(*cs->state.vs_consts_i) * 4 * op->vector4i_count);
+
+    device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->vector4i_count - 1);
+}
+
+static UINT wined3d_cs_exec_set_ps_consts_i(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_i *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(&cs->state.ps_consts_i[op->start_register * 4], op->constants,
+            sizeof(*cs->state.ps_consts_i) * 4 * op->vector4i_count);
+
+    device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->vector4i_count - 1);
+}
+
+void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register,
+        const int *constants, UINT vector4i_count, enum wined3d_shader_type type)
+{
+    struct wined3d_cs_set_consts_i *op;
+    UINT extra_space = vector4i_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_I;
+            break;
+
+        case WINED3D_SHADER_TYPE_VERTEX:
+            op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_I;
+            break;
+
+        case WINED3D_SHADER_TYPE_GEOMETRY:
+            ERR("Invalid for geometry shaders\n");
+            return;
+
+        case WINED3D_SHADER_TYPE_COUNT:
+            break;
+    }
+    op->start_register = start_register;
+    op->vector4i_count = vector4i_count;
+    memcpy(op->constants, constants, sizeof(op->constants) * vector4i_count);
+
+    cs->ops->submit(cs);
+}
+
 static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_cs_set_texture_state *op = data;
@@ -1442,8 +1502,10 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* 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_VS_CONSTS_B            */ wined3d_cs_exec_set_vs_consts_b,
+    /* WINED3D_CS_OP_SET_VS_CONSTS_I            */ wined3d_cs_exec_set_vs_consts_i,
     /* WINED3D_CS_OP_SET_PS_CONSTS_F            */ wined3d_cs_exec_set_ps_consts_f,
     /* WINED3D_CS_OP_SET_PS_CONSTS_B            */ wined3d_cs_exec_set_ps_consts_b,
+    /* WINED3D_CS_OP_SET_PS_CONSTS_I            */ wined3d_cs_exec_set_ps_consts_i,
     /* WINED3D_CS_OP_GLFINISH                   */ wined3d_cs_exec_glfinish,
     /* WINED3D_CS_OP_SET_BASE_VERTEX_INDEX      */ wined3d_cs_exec_set_base_vertex_index,
     /* WINED3D_CS_OP_SET_PRIMITIVE_TYPE         */ wined3d_cs_exec_set_primitive_type,
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 14d3080..9ba40df 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2278,7 +2278,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_i(struct wined3d_device *device,
     }
     else
     {
-        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_I);
+        wined3d_cs_emit_set_consts_i(device->cs, start_register, constants,
+                vector4i_count, WINED3D_SHADER_TYPE_VERTEX);
     }
 
     return WINED3D_OK;
@@ -2513,7 +2514,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_i(struct wined3d_device *device,
     }
     else
     {
-        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_I);
+        wined3d_cs_emit_set_consts_i(device->cs, start_register, constants,
+                vector4i_count, WINED3D_SHADER_TYPE_PIXEL);
     }
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 4ecb626..59149bd 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2618,6 +2618,8 @@ void wined3d_cs_emit_set_consts_f(struct wined3d_cs *cs, UINT start_register, co
         UINT vector4f_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_consts_b(struct wined3d_cs *cs, UINT start_register,
         const BOOL *constants, UINT bool_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_set_consts_i(struct wined3d_cs *cs, UINT start_register,
+        const int *constants, UINT vector4i_count, enum wined3d_shader_type type) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_glfinish(struct wined3d_cs *cs) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_set_base_vertex_index(struct wined3d_cs *cs,
         UINT base_vertex_index) DECLSPEC_HIDDEN;
-- 
2.1.3

