From 4c5581c2eb7ed40185807082241662001e317f98 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Fri, 4 Dec 2020 18:15:32 +0330 Subject: [PATCH] wined3d: Use the "bo user" mechanism to invalidate existing bindings in wined3d_buffer_gl_destroy_buffer_object(). Signed-off-by: Henri Verbeet Signed-off-by: Alexandre Julliard --- 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.11.4.GIT