From cba6a35d48886d00959d29d4fef9115a46143589 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20D=C3=B6singer?= <stefan@codeweavers.com>
Date: Wed, 20 Aug 2014 18:01:36 +0200
Subject: wined3d: Introduce resource fencing.

FIXME: The buffer part doesn't really make sense without dynamic buffer maps.
---
 dlls/wined3d/cs.c              | 19 +++++++++++++++++++
 dlls/wined3d/wined3d_private.h | 16 ++++++++++++++++
 2 files changed, 35 insertions(+)

diff --git a/dlls/wined3d/cs.c b/dlls/wined3d/cs.c
index 11aa133..1197eef 100644
--- a/dlls/wined3d/cs.c
+++ b/dlls/wined3d/cs.c
@@ -575,6 +575,7 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
 {
     const struct wined3d_cs_draw *op = data;
     const struct wined3d_gl_info *gl_info = &cs->device->adapter->gl_info;
+    unsigned int i;
 
     if (op->indexed && !gl_info->supported[ARB_DRAW_ELEMENTS_BASE_VERTEX])
     {
@@ -593,6 +594,14 @@ static UINT wined3d_cs_exec_draw(struct wined3d_cs *cs, const void *data)
     draw_primitive(cs->device, &cs->state, op->start_idx, op->index_count,
             op->start_instance, op->instance_count, op->indexed);
 
+    if (op->indexed)
+        wined3d_resource_dec_fence(&cs->state.index_buffer->resource);
+    for (i = 0; i < sizeof(cs->state.streams) / sizeof(*cs->state.streams); i++)
+    {
+        if (cs->state.streams[i].buffer)
+            wined3d_resource_dec_fence(&cs->state.streams[i].buffer->resource);
+    }
+
     return sizeof(*op);
 }
 
@@ -600,6 +609,8 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun
         UINT start_instance, UINT instance_count, BOOL indexed)
 {
     struct wined3d_cs_draw *op;
+    unsigned int i;
+    const struct wined3d_state *state = &cs->device->state;
 
     op = cs->ops->require_space(cs, sizeof(*op));
     op->opcode = WINED3D_CS_OP_DRAW;
@@ -609,6 +620,14 @@ void wined3d_cs_emit_draw(struct wined3d_cs *cs, UINT start_idx, UINT index_coun
     op->instance_count = instance_count;
     op->indexed = indexed;
 
+    if (indexed)
+        wined3d_resource_inc_fence(&state->index_buffer->resource);
+    for (i = 0; i < sizeof(state->streams) / sizeof(*state->streams); i++)
+    {
+        if (state->streams[i].buffer)
+            wined3d_resource_inc_fence(&state->streams[i].buffer->resource);
+    }
+
     cs->ops->submit(cs, sizeof(*op));
 }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 570f5e3..10d0789 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -2129,6 +2129,7 @@ struct wined3d_resource
     GLuint buffer_object;
     struct list resource_list_entry;
     DWORD locations;
+    LONG access_fence;
 
     void *parent;
     const struct wined3d_parent_ops *parent_ops;
@@ -2182,6 +2183,21 @@ void wined3d_resource_unmap_internal(struct wined3d_resource *resource) DECLSPEC
 void wined3d_resource_update_draw_binding(struct wined3d_resource *resource) DECLSPEC_HIDDEN;
 void wined3d_resource_validate_location(struct wined3d_resource *resource, DWORD location) DECLSPEC_HIDDEN;
 
+static inline void wined3d_resource_inc_fence(struct wined3d_resource *resource)
+{
+    InterlockedIncrement(&resource->access_fence);
+}
+
+static inline void wined3d_resource_dec_fence(struct wined3d_resource *resource)
+{
+    InterlockedDecrement(&resource->access_fence);
+}
+
+static inline void wined3d_resource_wait_fence(struct wined3d_resource *resource)
+{
+    while(InterlockedCompareExchange(&resource->access_fence, 0, 0));
+}
+
 /* Tests show that the start address of resources is 32 byte aligned */
 #define RESOURCE_ALIGNMENT 16
 
-- 
2.2.1

