From a94a1e128c6effd531b1722198dc63db0d1dbdc9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Sat, 6 Jul 2013 16:14:16 +0200
Subject: wined3d: Accelerate DISCARD buffer maps

TODO: Make this generic for all resources.
TODO2: Merge this with the patch that controlls BUFFER_DISCARD in the CS thread
TODO3: Clean up the map_mem allocation mess.
---
 dlls/wined3d/buffer.c          | 15 ++++++++++++---
 dlls/wined3d/cs.c              | 39 ++++++++++++++++++++++++++++++++++++++-
 dlls/wined3d/wined3d_private.h |  2 ++
 3 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index ae7d648..db2678c 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -1058,10 +1058,19 @@ HRESULT CDECL wined3d_buffer_map(struct wined3d_buffer *buffer, UINT offset, UIN
             buffer->flags |= WINED3D_BUFFER_SYNC;
     }
 
-    if (!(flags & WINED3D_MAP_NOOVERWRITE) && wined3d_settings.cs_multithreaded)
+    if (wined3d_settings.cs_multithreaded && count == 1)
     {
-        FIXME("waiting for cs.\n");
-        device->cs->ops->finish(device->cs);
+        BOOL swvp = device->create_parms.flags & WINED3DCREATE_SOFTWARE_VERTEXPROCESSING;
+        if (flags & WINED3D_MAP_DISCARD && !swvp)
+        {
+            wined3d_resource_allocate_sysmem(&buffer->resource);
+            wined3d_cs_emit_buffer_swap_mem(device->cs, buffer, buffer->resource.map_heap_memory);
+        }
+        else if(!(flags & WINED3D_MAP_NOOVERWRITE))
+        {
+            FIXME("waiting for cs.\n");
+            device->cs->ops->finish(device->cs);
+        }
     }
 
     base = buffer->map_ptr ? buffer->map_ptr : buffer->resource.map_heap_memory;
diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 4973041..cd234d3 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -69,6 +69,7 @@ enum wined3d_cs_op
     WINED3D_CS_OP_RESOURCE_CHANGED,
     WINED3D_CS_OP_RESOURCE_MAP,
     WINED3D_CS_OP_RESOURCE_UNMAP,
+    WINED3D_CS_OP_BUFFER_SWAP_MEM,
     WINED3D_CS_OP_QUERY_ISSUE,
     WINED3D_CS_OP_QUERY_DESTROY,
     WINED3D_CS_OP_TEXTURE_PRELOAD,
@@ -382,6 +383,13 @@ struct wined3d_cs_resource_changed
     void *swap_heap_memory;
 };
 
+struct wined3d_cs_buffer_swap_mem
+{
+    enum wined3d_cs_op opcode;
+    struct wined3d_buffer *buffer;
+    BYTE *mem;
+};
+
 struct wined3d_cs_skip
 {
     enum wined3d_cs_op opcode;
@@ -2140,6 +2148,34 @@ void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resour
     cs->ops->submit(cs, sizeof(*op));
 }
 
+static UINT wined3d_cs_exec_buffer_swap_mem(struct wined3d_cs *cs, const void *data)
+{
+    const struct wined3d_cs_buffer_swap_mem *op = data;
+    struct wined3d_buffer *buffer = op->buffer;
+
+    wined3d_resource_free_sysmem(&buffer->resource);
+    buffer->resource.heap_memory = op->mem;
+
+    if (!buffer->buffer_object && buffer->resource.bind_count)
+    {
+        device_invalidate_state(cs->device, STATE_STREAMSRC);
+        device_invalidate_state(cs->device, STATE_INDEXBUFFER);
+    }
+    return sizeof(*op);
+}
+
+void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffer *buffer, BYTE *mem)
+{
+    struct wined3d_cs_buffer_swap_mem *op;
+
+    op = cs->ops->require_space(cs, sizeof(*op));
+    op->opcode = WINED3D_CS_OP_BUFFER_SWAP_MEM;
+    op->buffer = buffer;
+    op->mem = mem;
+
+    cs->ops->submit(cs, sizeof(*op));
+}
+
 static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void *data) =
 {
     /* WINED3D_CS_OP_NOP                        */ wined3d_cs_exec_nop,
@@ -2160,11 +2196,11 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* 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_TEXTURE                */ wined3d_cs_exec_set_texture,
+    /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW   */ wined3d_cs_exec_set_shader_resource_view,
     /* WINED3D_CS_OP_SET_SAMPLER                */ wined3d_cs_exec_set_sampler,
     /* WINED3D_CS_OP_SET_SHADER                 */ wined3d_cs_exec_set_shader,
     /* WINED3D_CS_OP_SET_RENDER_STATE           */ wined3d_cs_exec_set_render_state,
     /* WINED3D_CS_OP_SET_TEXTURE_STATE          */ wined3d_cs_exec_set_texture_state,
-    /* WINED3D_CS_OP_SET_SHADER_RESOURCE_VIEW   */ wined3d_cs_exec_set_shader_resource_view,
     /* WINED3D_CS_OP_SET_SAMPLER_STATE          */ wined3d_cs_exec_set_sampler_state,
     /* WINED3D_CS_OP_SET_TRANSFORM              */ wined3d_cs_exec_set_transform,
     /* WINED3D_CS_OP_SET_CLIP_PLANE             */ wined3d_cs_exec_set_clip_plane,
@@ -2187,6 +2223,7 @@ static UINT (* const wined3d_cs_op_handlers[])(struct wined3d_cs *cs, const void
     /* WINED3D_CS_OP_RESOURCE_CHANGED           */ wined3d_cs_exec_resource_changed,
     /* WINED3D_CS_OP_RESOURCE_MAP               */ wined3d_cs_exec_resource_map,
     /* WINED3D_CS_OP_RESOURCE_UNMAP             */ wined3d_cs_exec_resource_unmap,
+    /* WINED3D_CS_OP_BUFFER_SWAP_MEM            */ wined3d_cs_exec_buffer_swap_mem,
     /* WINED3D_CS_OP_QUERY_ISSUE                */ wined3d_cs_exec_query_issue,
     /* WINED3D_CS_OP_QUERY_DESTROY              */ wined3d_cs_exec_query_destroy,
     /* WINED3D_CS_OP_TEXTURE_PRELOAD            */ wined3d_cs_exec_texture_preload,
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 53a1cf7..b0390e3 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2902,6 +2902,8 @@ void wined3d_cs_emit_texture_preload(struct wined3d_cs *cs, struct wined3d_textu
 void wined3d_cs_emit_update_texture(struct wined3d_cs *cs, struct wined3d_texture *src,
         struct wined3d_texture *dst) DECLSPEC_HIDDEN;
 void wined3d_cs_emit_evict_resource(struct wined3d_cs *cs, struct wined3d_resource *resource) DECLSPEC_HIDDEN;
+void wined3d_cs_emit_buffer_swap_mem(struct wined3d_cs *cs, struct wined3d_buffer *buffer,
+        BYTE *mem) 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.7.0

