From 870ae689d58feb0e2c28603ab7a5c202dc1bf6c2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Tue, 9 Apr 2013 21:50:30 +0200
Subject: wined3d: Send bool constant updates through the command stream

---
 dlls/wined3d/cs.c              | 72 +++++++++++++++++++++++++++++++++++++++---
 dlls/wined3d/device.c          |  8 +++--
 dlls/wined3d/wined3d_private.h |  3 ++
 3 files changed, 76 insertions(+), 7 deletions(-)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index a7ba2b4..9d8491a 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -64,7 +64,9 @@ enum wined3d_cs_op
     WINED3D_CS_OP_RESET_STATE,
     WINED3D_CS_OP_STATEBLOCK,
     WINED3D_CS_OP_SET_VS_CONSTS_F,
+    WINED3D_CS_OP_SET_VS_CONSTS_B,
     WINED3D_CS_OP_SET_PS_CONSTS_F,
+    WINED3D_CS_OP_SET_PS_CONSTS_B,
     WINED3D_CS_OP_GLFINISH,
     WINED3D_CS_OP_SET_BASE_VERTEX_INDEX,
     WINED3D_CS_OP_SET_PRIMITIVE_TYPE,
@@ -287,6 +289,13 @@ struct wined3d_cs_set_consts_f
     float constants[4];
 };
 
+struct wined3d_cs_set_consts_b
+{
+    enum wined3d_cs_op opcode;
+    UINT start_register, bool_count;
+    BOOL constants[1];
+};
+
 struct wined3d_cs_finish
 {
     enum wined3d_cs_op opcode;
@@ -959,10 +968,8 @@ 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_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.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.lights, op->state.lights, sizeof(cs->state.lights));
@@ -979,10 +986,8 @@ 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_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));
 
-    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));
 
     /* FIXME: This is not ideal. CS is still running synchronously, so this is ok.
@@ -1137,6 +1142,63 @@ void wined3d_cs_emit_set_render_state(struct wined3d_cs *cs, enum wined3d_render
     op->value = value;
 
     cs->ops->submit(cs);
+};
+
+static UINT wined3d_cs_exec_set_vs_consts_b(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_b *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(&cs->state.vs_consts_b[op->start_register], op->constants,
+            sizeof(*cs->state.vs_consts_b) * op->bool_count);
+
+    device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->bool_count - 1);
+}
+
+static UINT wined3d_cs_exec_set_ps_consts_b(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_set_consts_b *op = data;
+    struct wined3d_device *device = cs->device;
+
+    memcpy(&cs->state.ps_consts_b[op->start_register], op->constants,
+            sizeof(*cs->state.ps_consts_b) * op->bool_count);
+
+    device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B);
+
+    return sizeof(*op) + sizeof(op->constants) * (op->bool_count - 1);
+}
+
+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)
+{
+    struct wined3d_cs_set_consts_b *op;
+    UINT extra_space = bool_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_B;
+            break;
+
+        case WINED3D_SHADER_TYPE_VERTEX:
+            op->opcode = WINED3D_CS_OP_SET_VS_CONSTS_B;
+            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->bool_count = bool_count;
+    memcpy(op->constants, constants, sizeof(op->constants) * bool_count);
+
+    cs->ops->submit(cs);
 }
 
 static UINT wined3d_cs_exec_set_texture_state(struct wined3d_cs *cs, const void *data)
@@ -1379,7 +1441,9 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* 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_VS_CONSTS_B            */ wined3d_cs_exec_set_vs_consts_b,
     /* 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_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 e87a52c..14d3080 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -2197,7 +2197,7 @@ struct wined3d_sampler * CDECL wined3d_device_get_vs_sampler(const struct wined3
     return device->state.sampler[WINED3D_SHADER_TYPE_VERTEX][idx];
 }
 
-static void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask)
+void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask)
 {
     UINT i;
 
@@ -2230,7 +2230,8 @@ HRESULT CDECL wined3d_device_set_vs_consts_b(struct wined3d_device *device,
     }
     else
     {
-        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_VS_B);
+        wined3d_cs_emit_set_consts_b(device->cs, start_register, constants,
+                bool_count, WINED3D_SHADER_TYPE_VERTEX);
     }
 
     return WINED3D_OK;
@@ -2464,7 +2465,8 @@ HRESULT CDECL wined3d_device_set_ps_consts_b(struct wined3d_device *device,
     }
     else
     {
-        device_invalidate_shader_constants(device, WINED3D_SHADER_CONST_PS_B);
+        wined3d_cs_emit_set_consts_b(device->cs, start_register, constants,
+                bool_count, WINED3D_SHADER_TYPE_PIXEL);
     }
 
     return WINED3D_OK;
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index a647ca9..4ecb626 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2058,6 +2058,7 @@ LRESULT device_process_message(struct wined3d_device *device, HWND window, BOOL
 void device_resource_add(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_resource_released(struct wined3d_device *device, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void device_invalidate_state(const struct wined3d_device *device, DWORD state) DECLSPEC_HIDDEN;
+void device_invalidate_shader_constants(const struct wined3d_device *device, DWORD mask) DECLSPEC_HIDDEN;
 
 static inline BOOL isStateDirty(const struct wined3d_context *context, DWORD state)
 {
@@ -2615,6 +2616,8 @@ void wined3d_cs_emit_set_vertex_declaration(struct wined3d_cs *cs,
 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;
+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_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

