[PATCH 1/4] wined3d: Use the "bo user" mechanism to invalidate existing bindings in wined3d_buffer_gl_destroy_buffer_object().

Henri Verbeet hverbeet at codeweavers.com
Fri Dec 4 08:45:32 CST 2020


Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
---
 dlls/wined3d/adapter_vk.c      |  6 ++---
 dlls/wined3d/buffer.c          | 47 +++++++++-------------------------
 dlls/wined3d/context_gl.c      | 20 ++++++++++++---
 dlls/wined3d/state.c           | 36 ++++++++++++++++++--------
 dlls/wined3d/wined3d_private.h |  8 +++---
 5 files changed, 62 insertions(+), 55 deletions(-)

diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c
index 3fb9e4ce4b4..3da1615b1b5 100644
--- a/dlls/wined3d/adapter_vk.c
+++ b/dlls/wined3d/adapter_vk.c
@@ -860,10 +860,10 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context,
 {
     struct wined3d_context_vk *context_vk = wined3d_context_vk(context);
     const struct wined3d_vk_info *vk_info;
-    struct wined3d_bo_user_vk *bo_user_vk;
     struct wined3d_device_vk *device_vk;
     VkCommandBuffer vk_command_buffer;
     VkBufferMemoryBarrier vk_barrier;
+    struct wined3d_bo_user *bo_user;
     struct wined3d_bo_vk *bo, tmp;
     VkMappedMemoryRange range;
     void *map_ptr;
@@ -886,9 +886,9 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context,
             *bo = tmp;
             list_init(&bo->users);
             list_move_head(&bo->users, &tmp.users);
-            LIST_FOR_EACH_ENTRY(bo_user_vk, &bo->users, struct wined3d_bo_user_vk, entry)
+            LIST_FOR_EACH_ENTRY(bo_user, &bo->users, struct wined3d_bo_user, entry)
             {
-                bo_user_vk->valid = false;
+                bo_user->valid = false;
             }
 
             goto map;
diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c
index 5dbc66449f4..e179f202cb8 100644
--- a/dlls/wined3d/buffer.c
+++ b/dlls/wined3d/buffer.c
@@ -143,47 +143,22 @@ static void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *bu
         struct wined3d_context_gl *context_gl)
 {
     struct wined3d_resource *resource = &buffer_gl->b.resource;
-    struct wined3d_buffer *buffer = &buffer_gl->b;
-    struct wined3d_cs *cs = resource->device->cs;
 
     if (!buffer_gl->b.buffer_object)
         return;
 
-    /* The stream source state handler might have read the memory of the
-     * vertex buffer already and got the memory in the vbo which is not
-     * valid any longer. Dirtify the stream source to force a reload. This
-     * happens only once per changed vertexbuffer and should occur rather
-     * rarely. */
-    if (resource->bind_count)
-    {
-        if (resource->bind_flags & WINED3D_BIND_VERTEX_BUFFER)
-            device_invalidate_state(resource->device, STATE_STREAMSRC);
-        if (resource->bind_flags & WINED3D_BIND_INDEX_BUFFER
-                && cs->state.index_buffer == buffer)
-            device_invalidate_state(resource->device, STATE_INDEXBUFFER);
-        if (resource->bind_flags & WINED3D_BIND_CONSTANT_BUFFER)
-        {
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX));
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL));
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN));
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY));
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL));
-            device_invalidate_state(resource->device, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE));
-        }
-        if (resource->bind_flags & WINED3D_BIND_STREAM_OUTPUT)
-        {
-            device_invalidate_state(resource->device, STATE_STREAM_OUTPUT);
-            if (context_gl->c.transform_feedback_active)
-            {
-                /* We have to make sure that transform feedback is not active
-                 * when deleting a potentially bound transform feedback buffer.
-                 * This may happen when the device is being destroyed. */
-                WARN("Deleting buffer object for buffer %p, disabling transform feedback.\n", buffer_gl);
-                wined3d_context_gl_end_transform_feedback(context_gl);
-            }
-        }
+    if (context_gl->c.transform_feedback_active && resource->bind_count
+            && resource->bind_flags & WINED3D_BIND_STREAM_OUTPUT)
+    {
+        /* We have to make sure that transform feedback is not active
+         * when deleting a potentially bound transform feedback buffer.
+         * This may happen when the device is being destroyed. */
+        WARN("Deleting buffer object for buffer %p, disabling transform feedback.\n", buffer_gl);
+        wined3d_context_gl_end_transform_feedback(context_gl);
     }
 
+    buffer_gl->bo_user.valid = false;
+    list_remove(&buffer_gl->bo_user.entry);
     wined3d_context_gl_destroy_bo(context_gl, &buffer_gl->bo);
     buffer_gl->b.buffer_object = 0;
 
@@ -225,6 +200,8 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf
     if (!coherent && gl_info->supported[APPLE_FLUSH_BUFFER_RANGE])
         buffer_gl->b.flags |= WINED3D_BUFFER_APPLESYNC;
 
+    list_init(&buffer_gl->bo_user.entry);
+    list_add_head(&buffer_gl->bo.users, &buffer_gl->bo_user.entry);
     buffer_gl->b.buffer_object = (uintptr_t)bo;
     buffer_invalidate_bo_range(&buffer_gl->b, 0, 0);
 
diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c
index 406b325cda8..305ca0507ff 100644
--- a/dlls/wined3d/context_gl.c
+++ b/dlls/wined3d/context_gl.c
@@ -2823,6 +2823,7 @@ bool wined3d_context_gl_create_bo(struct wined3d_context_gl *context_gl, GLsizei
     bo->id = id;
     bo->binding = binding;
     bo->usage = usage;
+    list_init(&bo->users);
     bo->command_fence_id = 0;
 
     return true;
@@ -3718,6 +3719,8 @@ static void context_gl_load_shader_resources(struct wined3d_context_gl *context_
             buffer_gl = wined3d_buffer_gl(state->cb[i][j]);
             wined3d_buffer_load(&buffer_gl->b, &context_gl->c, state);
             wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
+            if (!buffer_gl->bo_user.valid)
+                device_invalidate_state(context_gl->c.device, STATE_CONSTANT_BUFFER(i));
         }
 
         for (j = 0; j < shader->reg_maps.sampler_map.count; ++j)
@@ -3793,6 +3796,8 @@ static void context_gl_load_stream_output_buffers(struct wined3d_context_gl *con
         wined3d_buffer_load(&buffer_gl->b, &context_gl->c, state);
         wined3d_buffer_invalidate_location(&buffer_gl->b, ~WINED3D_LOCATION_BUFFER);
         wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
+        if (!buffer_gl->bo_user.valid)
+            device_invalidate_state(context_gl->c.device, STATE_STREAM_OUTPUT);
     }
 }
 
@@ -3848,7 +3853,10 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
         e = &context->stream_info.elements[wined3d_bit_scan(&map)];
         buffer_gl = wined3d_buffer_gl(state->streams[e->stream_idx].buffer);
 
-        wined3d_buffer_load(&buffer_gl->b, context, state);
+        if (!buffer_gl->bo_user.valid)
+            device_invalidate_state(device, STATE_STREAMSRC);
+        else
+            wined3d_buffer_load(&buffer_gl->b, context, state);
         wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
     }
     /* Loading the buffers above may have invalidated the stream info. */
@@ -3862,6 +3870,8 @@ static BOOL context_apply_draw_state(struct wined3d_context *context,
         if (context->stream_info.all_vbo)
         {
             wined3d_buffer_load(&buffer_gl->b, context, state);
+            if (!buffer_gl->bo_user.valid)
+                device_invalidate_state(device, STATE_INDEXBUFFER);
             wined3d_context_gl_reference_bo(context_gl, &buffer_gl->bo);
         }
         else
@@ -4989,6 +4999,7 @@ void wined3d_context_gl_load_tex_coords(const struct wined3d_context_gl *context
             gl_info->gl_ops.gl.p_glTexCoordPointer(format_gl->vtx_format, format_gl->vtx_type, e->stride,
                     e->data.addr + state->load_base_vertex_index * e->stride);
             gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+            wined3d_buffer_gl(state->streams[e->stream_idx].buffer)->bo_user.valid = true;
         }
         else
         {
@@ -5077,6 +5088,7 @@ static void wined3d_context_gl_load_vertex_data(struct wined3d_context_gl *conte
         checkGLcall("glVertexPointer(...)");
         gl_info->gl_ops.gl.p_glEnableClientState(GL_VERTEX_ARRAY);
         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
+        wined3d_buffer_gl(state->streams[e->stream_idx].buffer)->bo_user.valid = true;
     }
 
     /* Normals */
@@ -5100,7 +5112,7 @@ static void wined3d_context_gl_load_vertex_data(struct wined3d_context_gl *conte
         checkGLcall("glNormalPointer(...)");
         gl_info->gl_ops.gl.p_glEnableClientState(GL_NORMAL_ARRAY);
         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
-
+        wined3d_buffer_gl(state->streams[e->stream_idx].buffer)->bo_user.valid = true;
     }
     else
     {
@@ -5130,7 +5142,7 @@ static void wined3d_context_gl_load_vertex_data(struct wined3d_context_gl *conte
         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
         gl_info->gl_ops.gl.p_glEnableClientState(GL_COLOR_ARRAY);
         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
-
+        wined3d_buffer_gl(state->streams[e->stream_idx].buffer)->bo_user.valid = true;
     }
     else
     {
@@ -5199,6 +5211,7 @@ static void wined3d_context_gl_load_vertex_data(struct wined3d_context_gl *conte
             }
             gl_info->gl_ops.gl.p_glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
             checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
+            wined3d_buffer_gl(state->streams[e->stream_idx].buffer)->bo_user.valid = true;
         }
         else
         {
@@ -5292,6 +5305,7 @@ static void wined3d_context_gl_load_numbered_arrays(struct wined3d_context_gl *c
 
         format_gl = wined3d_format_gl(element->format);
         stream = &state->streams[element->stream_idx];
+        wined3d_buffer_gl(stream->buffer)->bo_user.valid = true;
 
         if ((stream->flags & WINED3DSTREAMSOURCE_INSTANCEDATA) && !context->instance_count)
             context->instance_count = state->streams[0].frequency;
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 71f7ac53a2f..e40c23daf03 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -4452,12 +4452,17 @@ static void indexbuffer(struct wined3d_context *context, const struct wined3d_st
 {
     const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
     const struct wined3d_stream_info *stream_info = &context->stream_info;
-    const struct wined3d_buffer *ib = state->index_buffer;
+    struct wined3d_buffer_gl *buffer_gl;
 
-    if (!ib || !stream_info->all_vbo)
+    if (!state->index_buffer || !stream_info->all_vbo)
+    {
         GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
-    else
-        GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wined3d_buffer_gl_const(ib)->bo.id));
+        return;
+    }
+
+    buffer_gl = wined3d_buffer_gl(state->index_buffer);
+    GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer_gl->bo.id));
+    buffer_gl->bo_user.valid = true;
 }
 
 static void depth_clip(const struct wined3d_rasterizer_state *r, const struct wined3d_gl_info *gl_info)
@@ -4550,7 +4555,7 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state
 {
     const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
     enum wined3d_shader_type shader_type;
-    struct wined3d_buffer *buffer;
+    struct wined3d_buffer_gl *buffer_gl;
     unsigned int i, base, count;
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
@@ -4563,8 +4568,15 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state
     wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, shader_type, &base, &count);
     for (i = 0; i < count; ++i)
     {
-        buffer = state->cb[shader_type][i];
-        GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, buffer ? wined3d_buffer_gl(buffer)->bo.id : 0));
+        if (!state->cb[shader_type][i])
+        {
+            GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, 0));
+            continue;
+        }
+
+        buffer_gl = wined3d_buffer_gl(state->cb[shader_type][i]);
+        GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i, buffer_gl->bo.id));
+        buffer_gl->bo_user.valid = true;
     }
     checkGLcall("bind constant buffers");
 }
@@ -4614,7 +4626,7 @@ static void state_so(struct wined3d_context *context, const struct wined3d_state
 {
     struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
     const struct wined3d_gl_info *gl_info = context_gl->gl_info;
-    struct wined3d_buffer *buffer;
+    struct wined3d_buffer_gl *buffer_gl;
     unsigned int offset, size, i;
 
     TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
@@ -4623,20 +4635,22 @@ static void state_so(struct wined3d_context *context, const struct wined3d_state
 
     for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
     {
-        if (!(buffer = state->stream_output[i].buffer))
+        if (!state->stream_output[i].buffer)
         {
             GL_EXTCALL(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, 0));
             continue;
         }
 
+        buffer_gl = wined3d_buffer_gl(state->stream_output[i].buffer);
         offset = state->stream_output[i].offset;
         if (offset == ~0u)
         {
             FIXME("Appending to stream output buffers not implemented.\n");
             offset = 0;
         }
-        size = buffer->resource.size - offset;
-        GL_EXTCALL(glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, wined3d_buffer_gl(buffer)->bo.id, offset, size));
+        size = buffer_gl->b.resource.size - offset;
+        GL_EXTCALL(glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, buffer_gl->bo.id, offset, size));
+        buffer_gl->bo_user.valid = true;
     }
     checkGLcall("bind transform feedback buffers");
 }
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 67caf98ead7..67a55c4dedd 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -1575,6 +1575,7 @@ struct wined3d_bo_gl
     GLenum binding;
     GLenum usage;
 
+    struct list users;
     uint64_t command_fence_id;
 };
 
@@ -1583,7 +1584,7 @@ static inline GLuint wined3d_bo_gl_id(uintptr_t bo)
     return bo ? ((struct wined3d_bo_gl *)bo)->id : 0;
 }
 
-struct wined3d_bo_user_vk
+struct wined3d_bo_user
 {
     struct list entry;
     bool valid;
@@ -4875,6 +4876,7 @@ struct wined3d_buffer_gl
     struct wined3d_buffer b;
 
     struct wined3d_bo_gl bo;
+    struct wined3d_bo_user bo_user;
 };
 
 static inline struct wined3d_buffer_gl *wined3d_buffer_gl(struct wined3d_buffer *buffer)
@@ -4898,7 +4900,7 @@ struct wined3d_buffer_vk
     struct wined3d_buffer b;
 
     struct wined3d_bo_vk bo;
-    struct wined3d_bo_user_vk bo_user;
+    struct wined3d_bo_user bo_user;
     VkDescriptorBufferInfo buffer_info;
 };
 
@@ -5029,7 +5031,7 @@ HRESULT wined3d_shader_resource_view_gl_init(struct wined3d_shader_resource_view
 
 struct wined3d_view_vk
 {
-    struct wined3d_bo_user_vk bo_user;
+    struct wined3d_bo_user bo_user;
     union
     {
         VkBufferView vk_buffer_view;
-- 
2.20.1




More information about the wine-devel mailing list