From b2f13103d7d96fc082b91b8e808599836ed4a2b1 Mon Sep 17 00:00:00 2001 From: Zebediah Figura Date: Mon, 17 Jul 2023 19:36:54 -0500 Subject: [PATCH] wined3d: Remove BO users from the list when invalidating them. This makes it easier to invalidate in the case where multiple resources share the same BO, which in turn is necessary to implement copy-on-write semantics for BOs. This is also necessary if we ever want to evict resources which have views, although it's not clear if this will ever be necessary. If nothing else, though, it removes that implicit dependency. --- dlls/wined3d/adapter_vk.c | 11 +++++------ dlls/wined3d/buffer.c | 26 +++++++++++++------------- dlls/wined3d/context_gl.c | 24 ++++++++++++------------ dlls/wined3d/context_vk.c | 2 ++ dlls/wined3d/state.c | 6 +++--- dlls/wined3d/texture.c | 3 ++- dlls/wined3d/view.c | 21 +++++++++++++++++---- dlls/wined3d/wined3d_private.h | 8 ++++++++ 8 files changed, 62 insertions(+), 39 deletions(-) diff --git a/dlls/wined3d/adapter_vk.c b/dlls/wined3d/adapter_vk.c index a03ec37161e..6a030f0440a 100644 --- a/dlls/wined3d/adapter_vk.c +++ b/dlls/wined3d/adapter_vk.c @@ -921,16 +921,15 @@ static void *adapter_vk_map_bo_address(struct wined3d_context *context, if (wined3d_context_vk_create_bo(context_vk, bo->size, bo->usage, bo->memory_type, &tmp)) { bool host_synced = bo->host_synced; - list_move_head(&tmp.b.users, &bo->b.users); + + LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) + bo_user->valid = false; + list_init(&bo->b.users); + wined3d_context_vk_destroy_bo(context_vk, bo); *bo = tmp; bo->host_synced = host_synced; list_init(&bo->b.users); - list_move_head(&bo->b.users, &tmp.b.users); - LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) - { - bo_user->valid = false; - } goto map; } diff --git a/dlls/wined3d/buffer.c b/dlls/wined3d/buffer.c index efbd3233428..de1cf90d055 100644 --- a/dlls/wined3d/buffer.c +++ b/dlls/wined3d/buffer.c @@ -194,8 +194,11 @@ static void wined3d_buffer_gl_destroy_buffer_object(struct wined3d_buffer_gl *bu wined3d_context_gl_end_transform_feedback(context_gl); } - buffer_gl->b.bo_user.valid = false; - list_remove(&buffer_gl->b.bo_user.entry); + if (buffer_gl->b.bo_user.valid) + { + buffer_gl->b.bo_user.valid = false; + list_remove(&buffer_gl->b.bo_user.entry); + } wined3d_context_gl_destroy_bo(context_gl, bo_gl); heap_free(bo_gl); buffer_gl->b.buffer_object = NULL; @@ -237,7 +240,6 @@ static BOOL wined3d_buffer_gl_create_buffer_object(struct wined3d_buffer_gl *buf return FALSE; } - list_add_head(&bo->b.users, &buffer_gl->b.bo_user.entry); buffer_gl->b.buffer_object = &bo->b; buffer_invalidate_bo_range(&buffer_gl->b, 0, 0); @@ -1127,16 +1129,13 @@ static void wined3d_buffer_set_bo(struct wined3d_buffer *buffer, struct wined3d_ LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->users, struct wined3d_bo_user, entry) bo_user->valid = false; + list_init(&prev_bo->users); + assert(list_empty(&bo->users)); - list_move_head(&bo->users, &prev_bo->users); wined3d_context_destroy_bo(context, prev_bo); heap_free(prev_bo); } - else - { - list_add_head(&bo->users, &buffer->bo_user.entry); - } buffer->buffer_object = bo; } @@ -1516,8 +1515,6 @@ static BOOL wined3d_buffer_vk_create_buffer_object(struct wined3d_buffer_vk *buf return FALSE; } - list_init(&buffer_vk->b.bo_user.entry); - list_add_head(&bo_vk->b.users, &buffer_vk->b.bo_user.entry); buffer_vk->b.buffer_object = &bo_vk->b; buffer_invalidate_bo_range(&buffer_vk->b, 0, 0); @@ -1534,7 +1531,7 @@ const VkDescriptorBufferInfo *wined3d_buffer_vk_get_buffer_info(struct wined3d_b buffer_vk->buffer_info.buffer = bo->vk_buffer; buffer_vk->buffer_info.offset = bo->b.buffer_offset; buffer_vk->buffer_info.range = buffer_vk->b.resource.size; - buffer_vk->b.bo_user.valid = true; + wined3d_buffer_validate_user(&buffer_vk->b); return &buffer_vk->buffer_info; } @@ -1570,8 +1567,11 @@ static void wined3d_buffer_vk_unload_location(struct wined3d_buffer *buffer, switch (location) { case WINED3D_LOCATION_BUFFER: - buffer->bo_user.valid = false; - list_remove(&buffer->bo_user.entry); + if (buffer->bo_user.valid) + { + buffer->bo_user.valid = false; + list_remove(&buffer->bo_user.entry); + } wined3d_context_vk_destroy_bo(context_vk, bo_vk); heap_free(bo_vk); buffer->buffer_object = NULL; diff --git a/dlls/wined3d/context_gl.c b/dlls/wined3d/context_gl.c index 03638666268..d6827c2c0de 100644 --- a/dlls/wined3d/context_gl.c +++ b/dlls/wined3d/context_gl.c @@ -2859,15 +2859,13 @@ static void *wined3d_bo_gl_map(struct wined3d_bo_gl *bo, struct wined3d_context_ if (wined3d_device_gl_create_bo(device_gl, context_gl, bo->size, bo->binding, bo->usage, bo->b.coherent, bo->flags, &tmp)) { - list_move_head(&tmp.b.users, &bo->b.users); + LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) + bo_user->valid = false; + list_init(&bo->b.users); + wined3d_context_gl_destroy_bo(context_gl, bo); *bo = tmp; list_init(&bo->b.users); - list_move_head(&bo->b.users, &tmp.b.users); - LIST_FOR_EACH_ENTRY(bo_user, &bo->b.users, struct wined3d_bo_user, entry) - { - bo_user->valid = false; - } goto map; } @@ -3153,6 +3151,8 @@ void wined3d_context_gl_destroy_bo(struct wined3d_context_gl *context_gl, struct TRACE("context_gl %p, bo %p.\n", context_gl, bo); + assert(list_empty(&bo->b.users)); + if (bo->memory) { unsigned int order = bo->memory->order; @@ -5421,7 +5421,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, get_vertex_attrib_pointer(e, state)); gl_info->gl_ops.gl.p_glEnableClientState(GL_TEXTURE_COORD_ARRAY); - state->streams[e->stream_idx].buffer->bo_user.valid = true; + wined3d_buffer_validate_user(state->streams[e->stream_idx].buffer); } else { @@ -5508,7 +5508,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)"); - state->streams[e->stream_idx].buffer->bo_user.valid = true; + wined3d_buffer_validate_user(state->streams[e->stream_idx].buffer); } /* Normals */ @@ -5531,7 +5531,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)"); - state->streams[e->stream_idx].buffer->bo_user.valid = true; + wined3d_buffer_validate_user(state->streams[e->stream_idx].buffer); } else { @@ -5560,7 +5560,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)"); - state->streams[e->stream_idx].buffer->bo_user.valid = true; + wined3d_buffer_validate_user(state->streams[e->stream_idx].buffer); } else { @@ -5624,7 +5624,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)"); - state->streams[e->stream_idx].buffer->bo_user.valid = true; + wined3d_buffer_validate_user(state->streams[e->stream_idx].buffer); } else { @@ -5725,7 +5725,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]; - stream->buffer->bo_user.valid = true; + wined3d_buffer_validate_user(stream->buffer); if (gl_info->supported[ARB_INSTANCED_ARRAYS]) diff --git a/dlls/wined3d/context_vk.c b/dlls/wined3d/context_vk.c index efc18e2ff69..932d2f5aa77 100644 --- a/dlls/wined3d/context_vk.c +++ b/dlls/wined3d/context_vk.c @@ -1080,6 +1080,8 @@ void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const TRACE("context_vk %p, bo %p.\n", context_vk, bo); + assert(list_empty(&bo->b.users)); + if (bo->command_buffer_id == context_vk->current_command_buffer.id) context_vk->retired_bo_size += bo->size; diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 26cae888345..502c59c1c52 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -4264,7 +4264,7 @@ static void indexbuffer(struct wined3d_context *context, const struct wined3d_st if (buffer->buffer_object) { GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, wined3d_bo_gl(buffer->buffer_object)->id)); - buffer->bo_user.valid = true; + wined3d_buffer_validate_user(buffer); } else { @@ -4394,7 +4394,7 @@ static void state_cb(struct wined3d_context *context, const struct wined3d_state bo_gl->id, bo_gl->b.buffer_offset + buffer_state->offset, min(buffer_state->size, buffer->resource.size - buffer_state->offset))); - buffer->bo_user.valid = true; + wined3d_buffer_validate_user(buffer); } checkGLcall("bind constant buffers"); } @@ -4471,7 +4471,7 @@ static void state_so(struct wined3d_context *context, const struct wined3d_state size = buffer->resource.size - offset; GL_EXTCALL(glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_gl->id, bo_gl->b.buffer_offset + offset, size)); - buffer->bo_user.valid = true; + wined3d_buffer_validate_user(buffer); } checkGLcall("bind transform feedback buffers"); } diff --git a/dlls/wined3d/texture.c b/dlls/wined3d/texture.c index 2b9d6e3a8b3..6b5d9eaf510 100644 --- a/dlls/wined3d/texture.c +++ b/dlls/wined3d/texture.c @@ -4649,8 +4649,9 @@ static void wined3d_texture_set_bo(struct wined3d_texture *texture, LIST_FOR_EACH_ENTRY(bo_user, &prev_bo->users, struct wined3d_bo_user, entry) bo_user->valid = false; + list_init(&prev_bo->users); + assert(list_empty(&bo->users)); - list_move_head(&bo->users, &prev_bo->users); wined3d_context_destroy_bo(context, prev_bo); heap_free(prev_bo); diff --git a/dlls/wined3d/view.c b/dlls/wined3d/view.c index fb6f5d545ba..755fd5b2648 100644 --- a/dlls/wined3d/view.c +++ b/dlls/wined3d/view.c @@ -997,9 +997,13 @@ void * CDECL wined3d_shader_resource_view_get_parent(const struct wined3d_shader void wined3d_shader_resource_view_gl_update(struct wined3d_shader_resource_view_gl *srv_gl, struct wined3d_context_gl *context_gl) { - create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc, - buffer_from_resource(srv_gl->v.resource), srv_gl->v.format); + struct wined3d_buffer *buffer = buffer_from_resource(srv_gl->v.resource); + + assert(!srv_gl->bo_user.valid); + + create_buffer_view(&srv_gl->gl_view, &context_gl->c, &srv_gl->v.desc, buffer, srv_gl->v.format); srv_gl->bo_user.valid = true; + list_add_head(&buffer->buffer_object->users, &srv_gl->bo_user.entry); } static void wined3d_shader_resource_view_gl_cs_init(void *object) @@ -1112,12 +1116,15 @@ void wined3d_shader_resource_view_vk_update_buffer(struct wined3d_shader_resourc struct wined3d_buffer_vk *buffer_vk; VkBufferView vk_buffer_view; + assert(!view_vk->bo_user.valid); + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id); if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk))) { view_vk->u.vk_buffer_view = vk_buffer_view; view_vk->bo_user.valid = true; + list_add_head(&buffer_vk->b.buffer_object->users, &view_vk->bo_user.entry); } } @@ -1715,9 +1722,12 @@ void wined3d_unordered_access_view_copy_counter(struct wined3d_unordered_access_ void wined3d_unordered_access_view_gl_update(struct wined3d_unordered_access_view_gl *uav_gl, struct wined3d_context_gl *context_gl) { - create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc, - buffer_from_resource(uav_gl->v.resource), uav_gl->v.format); + struct wined3d_buffer *buffer = buffer_from_resource(uav_gl->v.resource); + + assert(!uav_gl->bo_user.valid); + create_buffer_view(&uav_gl->gl_view, &context_gl->c, &uav_gl->v.desc, buffer, uav_gl->v.format); uav_gl->bo_user.valid = true; + list_add_head(&buffer->buffer_object->users, &uav_gl->bo_user.entry); } static void wined3d_unordered_access_view_gl_cs_init(void *object) @@ -2280,12 +2290,15 @@ void wined3d_unordered_access_view_vk_update(struct wined3d_unordered_access_vie struct wined3d_buffer_vk *buffer_vk; VkBufferView vk_buffer_view; + assert(!view_vk->bo_user.valid); + buffer_vk = wined3d_buffer_vk(buffer_from_resource(resource)); wined3d_context_vk_destroy_vk_buffer_view(context_vk, view_vk->u.vk_buffer_view, view_vk->command_buffer_id); if ((vk_buffer_view = wined3d_view_vk_create_vk_buffer_view(context_vk, desc, buffer_vk, view_format_vk))) { view_vk->u.vk_buffer_view = vk_buffer_view; view_vk->bo_user.valid = true; + list_add_head(&buffer_vk->b.buffer_object->users, &view_vk->bo_user.entry); } } diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index d5b2cc0e020..aca2f6c5f47 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -4394,6 +4394,14 @@ static inline struct wined3d_buffer *buffer_from_resource(struct wined3d_resourc return CONTAINING_RECORD(resource, struct wined3d_buffer, resource); } +static inline void wined3d_buffer_validate_user(struct wined3d_buffer *buffer) +{ + if (buffer->bo_user.valid) + return; + buffer->bo_user.valid = true; + list_add_head(&buffer->buffer_object->users, &buffer->bo_user.entry); +} + void wined3d_buffer_cleanup(struct wined3d_buffer *buffer) DECLSPEC_HIDDEN; void wined3d_buffer_copy(struct wined3d_buffer *dst_buffer, unsigned int dst_offset, struct wined3d_buffer *src_buffer, unsigned int src_offset, unsigned int size) DECLSPEC_HIDDEN; -- 2.11.4.GIT