diff options
author | Jordan Justen <jordan.l.justen@intel.com> | 2015-01-26 10:57:15 -0800 |
---|---|---|
committer | Jordan Justen <jordan.l.justen@intel.com> | 2015-06-04 14:45:12 -0700 |
commit | d13831e8fe9a58a9faec7ac17d397a5b7c03b631 (patch) | |
tree | c01bca7311b925896beb338c5eb9020c8a812b8f | |
parent | 71e94578779e4344066d434004fd85ca493de552 (diff) |
mesa/bo: Make bo locking more coarse grainedcoarse-bo-locks
SynMark's OglBatch7 calls BindBuffer a large percentage of time
compared to GPU work. Therefore the locks related to changing the
currently bound buffer become relatively expensive.
Signed-off-by: Jordan Justen <jordan.l.justen@intel.com>
-rw-r--r-- | src/mesa/main/bufferobj.c | 130 |
1 files changed, 86 insertions, 44 deletions
diff --git a/src/mesa/main/bufferobj.c b/src/mesa/main/bufferobj.c index 66dee68025..aef547bad8 100644 --- a/src/mesa/main/bufferobj.c +++ b/src/mesa/main/bufferobj.c @@ -53,6 +53,9 @@ /*#define VBO_DEBUG*/ /*#define BOUNDS_CHECK*/ +static void +bind_buffer_base_locked(struct gl_context *ctx, + GLenum target, GLuint index, GLuint buffer); /** * Used as a placeholder for buffer objects between glGenBuffers() and @@ -430,17 +433,16 @@ _mesa_delete_buffer_object(struct gl_context *ctx, * This is normally only called from the _mesa_reference_buffer_object() macro * when there's a real pointer change. */ -void -_mesa_reference_buffer_object_(struct gl_context *ctx, - struct gl_buffer_object **ptr, - struct gl_buffer_object *bufObj) +static void +reference_bufferobj_locked(struct gl_context *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *bufObj) { if (*ptr) { /* Unreference the old buffer */ GLboolean deleteFlag = GL_FALSE; struct gl_buffer_object *oldObj = *ptr; - mtx_lock(&oldObj->Mutex); assert(oldObj->RefCount > 0); oldObj->RefCount--; #if 0 @@ -448,7 +450,6 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, (void *) oldObj, oldObj->Name, oldObj->RefCount); #endif deleteFlag = (oldObj->RefCount == 0); - mtx_unlock(&oldObj->Mutex); if (deleteFlag) { @@ -470,7 +471,6 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, if (bufObj) { /* reference new buffer */ - mtx_lock(&bufObj->Mutex); if (bufObj->RefCount == 0) { /* this buffer's being deleted (look just above) */ /* Not sure this can every really happen. Warn if it does. */ @@ -485,11 +485,21 @@ _mesa_reference_buffer_object_(struct gl_context *ctx, #endif *ptr = bufObj; } - mtx_unlock(&bufObj->Mutex); } } +void +_mesa_reference_buffer_object_(struct gl_context *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *bufObj) +{ + mtx_lock(&ctx->Shared->Mutex); + reference_bufferobj_locked(ctx, ptr, bufObj); + mtx_unlock(&ctx->Shared->Mutex); +} + + /** * Initialize a buffer object to default values. */ @@ -885,12 +895,12 @@ _mesa_free_buffer_objects( struct gl_context *ctx ) } -bool -_mesa_handle_bind_buffer_gen(struct gl_context *ctx, - GLenum target, - GLuint buffer, - struct gl_buffer_object **buf_handle, - const char *caller) +static bool +handle_bind_buffer_gen_locked(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller) { struct gl_buffer_object *buf = *buf_handle; @@ -909,13 +919,28 @@ _mesa_handle_bind_buffer_gen(struct gl_context *ctx, _mesa_error(ctx, GL_OUT_OF_MEMORY, "%s", caller); return false; } - _mesa_HashInsert(ctx->Shared->BufferObjects, buffer, buf); + _mesa_HashInsertLocked(ctx->Shared->BufferObjects, buffer, buf); *buf_handle = buf; } return true; } +bool +_mesa_handle_bind_buffer_gen(struct gl_context *ctx, + GLenum target, + GLuint buffer, + struct gl_buffer_object **buf_handle, + const char *caller) +{ + bool result; + mtx_lock(&ctx->Shared->Mutex); + result = handle_bind_buffer_gen_locked(ctx, target, buffer, buf_handle, + caller); + mtx_unlock(&ctx->Shared->Mutex); + return result; +} + /** * Bind the specified target to buffer for the specified context. * Called by glBindBuffer() and other functions. @@ -949,14 +974,14 @@ bind_buffer_object(struct gl_context *ctx, GLenum target, GLuint buffer) } else { /* non-default buffer object */ - newBufObj = _mesa_lookup_bufferobj(ctx, buffer); - if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, - &newBufObj, "glBindBuffer")) + newBufObj = _mesa_lookup_bufferobj_locked(ctx, buffer); + if (!handle_bind_buffer_gen_locked(ctx, target, buffer, + &newBufObj, "glBindBuffer")) return; } /* bind new buffer */ - _mesa_reference_buffer_object(ctx, bindTarget, newBufObj); + reference_bufferobj_locked(ctx, bindTarget, newBufObj); } @@ -971,10 +996,12 @@ _mesa_update_default_objects_buffer_objects(struct gl_context *ctx) /* Bind the NullBufferObj to remove references to those * in the shared context hash table. */ + mtx_lock(&ctx->Shared->Mutex); bind_buffer_object( ctx, GL_ARRAY_BUFFER_ARB, 0); bind_buffer_object( ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0); bind_buffer_object( ctx, GL_PIXEL_PACK_BUFFER_ARB, 0); bind_buffer_object( ctx, GL_PIXEL_UNPACK_BUFFER_ARB, 0); + mtx_unlock(&ctx->Shared->Mutex); } @@ -1094,12 +1121,12 @@ _mesa_multi_bind_lookup_bufferobj(struct gl_context *ctx, * unbound from all arrays in the current context. */ static void -unbind(struct gl_context *ctx, - struct gl_buffer_object **ptr, - struct gl_buffer_object *obj) +unbind_locked(struct gl_context *ctx, + struct gl_buffer_object **ptr, + struct gl_buffer_object *obj) { if (*ptr == obj) { - _mesa_reference_buffer_object(ctx, ptr, ctx->Shared->NullBufferObj); + reference_bufferobj_locked(ctx, ptr, ctx->Shared->NullBufferObj); } } @@ -1160,7 +1187,13 @@ _mesa_BindBuffer(GLenum target, GLuint buffer) _mesa_debug(ctx, "glBindBuffer(%s, %u)\n", _mesa_lookup_enum_by_nr(target), buffer); + mtx_lock(&ctx->Shared->Mutex); bind_buffer_object(ctx, target, buffer); + mtx_unlock(&ctx->Shared->Mutex); + + if (MESA_VERBOSE & VERBOSE_API) + _mesa_debug(ctx, "glBindBuffer(%s, %u) exit\n", + _mesa_lookup_enum_by_nr(target), buffer); } @@ -1196,71 +1229,71 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) /* unbind any vertex pointers bound to this buffer */ for (j = 0; j < ARRAY_SIZE(vao->VertexBinding); j++) { - unbind(ctx, &vao->VertexBinding[j].BufferObj, bufObj); + unbind_locked(ctx, &vao->VertexBinding[j].BufferObj, bufObj); } if (ctx->Array.ArrayBufferObj == bufObj) { - _mesa_BindBuffer( GL_ARRAY_BUFFER_ARB, 0 ); + bind_buffer_object(ctx, GL_ARRAY_BUFFER_ARB, 0 ); } if (vao->IndexBufferObj == bufObj) { - _mesa_BindBuffer( GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); + bind_buffer_object(ctx, GL_ELEMENT_ARRAY_BUFFER_ARB, 0 ); } /* unbind ARB_draw_indirect binding point */ if (ctx->DrawIndirectBuffer == bufObj) { - _mesa_BindBuffer( GL_DRAW_INDIRECT_BUFFER, 0 ); + bind_buffer_object(ctx, GL_DRAW_INDIRECT_BUFFER, 0 ); } /* unbind ARB_copy_buffer binding points */ if (ctx->CopyReadBuffer == bufObj) { - _mesa_BindBuffer( GL_COPY_READ_BUFFER, 0 ); + bind_buffer_object(ctx, GL_COPY_READ_BUFFER, 0 ); } if (ctx->CopyWriteBuffer == bufObj) { - _mesa_BindBuffer( GL_COPY_WRITE_BUFFER, 0 ); + bind_buffer_object(ctx, GL_COPY_WRITE_BUFFER, 0 ); } /* unbind transform feedback binding points */ if (ctx->TransformFeedback.CurrentBuffer == bufObj) { - _mesa_BindBuffer( GL_TRANSFORM_FEEDBACK_BUFFER, 0 ); + bind_buffer_object(ctx, GL_TRANSFORM_FEEDBACK_BUFFER, 0 ); } for (j = 0; j < MAX_FEEDBACK_BUFFERS; j++) { if (ctx->TransformFeedback.CurrentObject->Buffers[j] == bufObj) { - _mesa_BindBufferBase( GL_TRANSFORM_FEEDBACK_BUFFER, j, 0 ); + bind_buffer_base_locked(ctx, GL_TRANSFORM_FEEDBACK_BUFFER, j, 0 ); } } /* unbind UBO binding points */ for (j = 0; j < ctx->Const.MaxUniformBufferBindings; j++) { if (ctx->UniformBufferBindings[j].BufferObject == bufObj) { - _mesa_BindBufferBase( GL_UNIFORM_BUFFER, j, 0 ); + bind_buffer_base_locked(ctx, GL_UNIFORM_BUFFER, j, 0 ); } } if (ctx->UniformBuffer == bufObj) { - _mesa_BindBuffer( GL_UNIFORM_BUFFER, 0 ); + bind_buffer_object(ctx, GL_UNIFORM_BUFFER, 0 ); } /* unbind Atomci Buffer binding points */ for (j = 0; j < ctx->Const.MaxAtomicBufferBindings; j++) { if (ctx->AtomicBufferBindings[j].BufferObject == bufObj) { - _mesa_BindBufferBase( GL_ATOMIC_COUNTER_BUFFER, j, 0 ); + bind_buffer_base_locked(ctx, GL_ATOMIC_COUNTER_BUFFER, j, 0 ); } } if (ctx->AtomicBuffer == bufObj) { - _mesa_BindBuffer( GL_ATOMIC_COUNTER_BUFFER, 0 ); + bind_buffer_object(ctx, GL_ATOMIC_COUNTER_BUFFER, 0); } /* unbind any pixel pack/unpack pointers bound to this buffer */ if (ctx->Pack.BufferObj == bufObj) { - _mesa_BindBuffer( GL_PIXEL_PACK_BUFFER_EXT, 0 ); + bind_buffer_object(ctx, GL_PIXEL_PACK_BUFFER_EXT, 0 ); } if (ctx->Unpack.BufferObj == bufObj) { - _mesa_BindBuffer( GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); + bind_buffer_object(ctx, GL_PIXEL_UNPACK_BUFFER_EXT, 0 ); } if (ctx->Texture.BufferObject == bufObj) { - _mesa_BindBuffer( GL_TEXTURE_BUFFER, 0 ); + bind_buffer_object(ctx, GL_TEXTURE_BUFFER, 0 ); } if (ctx->ExternalVirtualMemoryBuffer == bufObj) { @@ -1280,7 +1313,7 @@ _mesa_DeleteBuffers(GLsizei n, const GLuint *ids) * which would introduce more runtime overhead than this. */ bufObj->DeletePending = GL_TRUE; - _mesa_reference_buffer_object(ctx, &bufObj, NULL); + reference_bufferobj_locked(ctx, &bufObj, NULL); } } @@ -3904,10 +3937,10 @@ _mesa_BindBufferRange(GLenum target, GLuint index, } } -void GLAPIENTRY -_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) +static void +bind_buffer_base_locked(struct gl_context *ctx, + GLenum target, GLuint index, GLuint buffer) { - GET_CURRENT_CONTEXT(ctx); struct gl_buffer_object *bufObj; if (buffer == 0) { @@ -3915,8 +3948,8 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) } else { bufObj = _mesa_lookup_bufferobj(ctx, buffer); } - if (!_mesa_handle_bind_buffer_gen(ctx, target, buffer, - &bufObj, "glBindBufferBase")) + if (!handle_bind_buffer_gen_locked(ctx, target, buffer, + &bufObj, "glBindBufferBase")) return; if (!bufObj) { @@ -3971,6 +4004,15 @@ _mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) } void GLAPIENTRY +_mesa_BindBufferBase(GLenum target, GLuint index, GLuint buffer) +{ + GET_CURRENT_CONTEXT(ctx); + mtx_lock(&ctx->Shared->Mutex); + bind_buffer_base_locked(ctx, target, index, buffer); + mtx_unlock(&ctx->Shared->Mutex); +} + +void GLAPIENTRY _mesa_BindBuffersRange(GLenum target, GLuint first, GLsizei count, const GLuint *buffers, const GLintptr *offsets, const GLsizeiptr *sizes) |