From a8bb8f396bf22ce5650e9171df708b6e12c3f010 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Tue, 17 May 2011 14:19:21 +0200 Subject: [PATCH] Vertex buffer upload caching --- src/gallium/auxiliary/util/u_vbuf_mgr.c | 61 +++++++++++++++++++++++++++---- src/gallium/include/pipe/p_state.h | 3 ++ src/mesa/main/mtypes.h | 1 + src/mesa/main/state.c | 2 +- src/mesa/main/varray.c | 21 ++++++++++- src/mesa/state_tracker/st_draw.c | 11 ++++++ 6 files changed, 89 insertions(+), 10 deletions(-) diff --git a/src/gallium/auxiliary/util/u_vbuf_mgr.c b/src/gallium/auxiliary/util/u_vbuf_mgr.c index dea2928..bf5119b 100644 --- a/src/gallium/auxiliary/util/u_vbuf_mgr.c +++ b/src/gallium/auxiliary/util/u_vbuf_mgr.c @@ -65,6 +65,15 @@ struct u_vbuf_mgr_elements { boolean incompatible_layout; }; +struct vb_cache { + unsigned first, size; + void* buffer_src; + boolean flushed; + unsigned offset; + struct pipe_resource * buffer; +}; + + struct u_vbuf_mgr_priv { struct u_vbuf_mgr b; struct u_vbuf_caps caps; @@ -73,6 +82,8 @@ struct u_vbuf_mgr_priv { struct translate_cache *translate_cache; unsigned translate_vb_slot; + struct vb_cache vb_upload_caches[PIPE_MAX_SHADER_INPUTS]; + struct u_vbuf_mgr_elements *ve; void *saved_ve, *fallback_ve; boolean ve_binding_lock; @@ -477,6 +488,14 @@ void u_vbuf_mgr_set_vertex_buffers(struct u_vbuf_mgr *mgrb, } } + // clear cache if requested + for(int i=0 ; ivb_upload_caches[i].buffer, NULL); + memset(&mgr->vb_upload_caches[i], 0, sizeof(struct vb_cache)); + } + } + for (i = 0; i < count; i++) { const struct pipe_vertex_buffer *vb = &bufs[i]; @@ -545,13 +564,41 @@ static void u_vbuf_upload_buffers(struct u_vbuf_mgr_priv *mgr, first = 0; size = mgr->ve->native_format_size[i]; } - - u_upload_data(mgr->b.uploader, first, size, - u_vbuf_resource(vb->buffer)->user_ptr + first, - &vb->buffer_offset, - &mgr->b.real_vertex_buffer[index], - &flushed); - + const void* buffer_src = u_vbuf_resource(vb->buffer)->user_ptr + first; + bool debug_option = debug_get_bool_option("UPLOAD_CACHING", FALSE); + // do we need to upload this vertex buffer ? + if (!debug_option || // caching disabled ? + !vb->lock_count || // glLockArrays API not used ? + !mgr->vb_upload_caches[i].buffer || // no existing buf to reuse + mgr->vb_upload_caches[i].first != first ||// 'first' param do not match cache's one + mgr->vb_upload_caches[i].size != size || // 'size' param don't match + mgr->vb_upload_caches[i].buffer_src != buffer_src) // 'user_ptr' don't match + { + // upload vertex buffer + u_upload_data(mgr->b.uploader, first, size, + buffer_src, + &vb->buffer_offset, + &mgr->b.real_vertex_buffer[index], + &flushed); + // cache vb if allowed + if (debug_option && vb->lock_first <= min_index && vb->lock_count >= count) { + mgr->vb_upload_caches[i].first = first; + mgr->vb_upload_caches[i].size = size; + mgr->vb_upload_caches[i].buffer_src = buffer_src; + mgr->vb_upload_caches[i].offset = vb->buffer_offset; + mgr->vb_upload_caches[i].flushed = flushed; + pipe_resource_reference(&mgr->vb_upload_caches[i].buffer, mgr->b.real_vertex_buffer[index]); + } else { + pipe_resource_reference(&mgr->vb_upload_caches[i].buffer, NULL); + memset(&mgr->vb_upload_caches[i], 0, sizeof(struct vb_cache)); + } + } + // reuse existing buffer + else { + vb->buffer_offset = mgr->vb_upload_caches[i].offset; + flushed = true;//mgr->vb_upload_caches[i].flushed; + pipe_resource_reference(&mgr->b.real_vertex_buffer[index], mgr->vb_upload_caches[i].buffer); + } vb->buffer_offset -= first; uploaded[index] = TRUE; diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h index f6ad456..6e200fe 100644 --- a/src/gallium/include/pipe/p_state.h +++ b/src/gallium/include/pipe/p_state.h @@ -412,6 +412,9 @@ struct pipe_vertex_buffer unsigned stride; /**< stride to same attrib in next vertex, in bytes */ unsigned buffer_offset; /**< offset to start of data in buffer, in bytes */ struct pipe_resource *buffer; /**< the actual buffer */ + + unsigned lock_first, lock_count; + bool flush_lock_cache; }; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index fba65e8..07167ae 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1609,6 +1609,7 @@ struct gl_client_array GLboolean Enabled; /**< Enabled flag is a boolean */ GLboolean Normalized; /**< GL_ARB_vertex_program */ GLboolean Integer; /**< Integer-valued? */ + GLboolean EnabledBeforeLock; GLuint InstanceDivisor; /**< GL_ARB_instanced_arrays */ GLuint _ElementSize; /**< size of each element in bytes */ diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index 4696dbb..33a4c15 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -670,7 +670,7 @@ _mesa_update_state_locked( struct gl_context *ctx ) new_state = ctx->NewState | new_prog_state; ctx->NewState = 0; ctx->Driver.UpdateState(ctx, new_state); - ctx->Array.NewState = 0; +// ctx->Array.NewState = 0; if (!ctx->Array.RebindArrays) ctx->Array.RebindArrays = (new_state & (_NEW_ARRAY | _NEW_PROGRAM)) != 0; } diff --git a/src/mesa/main/varray.c b/src/mesa/main/varray.c index d20e2c7..e98d597 100644 --- a/src/mesa/main/varray.c +++ b/src/mesa/main/varray.c @@ -185,6 +185,7 @@ update_array(struct gl_context *ctx, array->Normalized = normalized; array->Ptr = (const GLubyte *) ptr; array->_ElementSize = elementSize; + array->EnabledBeforeLock = GL_FALSE; _mesa_reference_buffer_object(ctx, &array->BufferObj, ctx->Array.ArrayBufferObj); @@ -940,6 +941,10 @@ void GLAPIENTRY _mesa_LockArraysEXT(GLint first, GLsizei count) { GET_CURRENT_CONTEXT(ctx); +#define UPDATE_ENABLED_BEFORE_LOCK(array) if (ctx->Array.ArrayObj->array.Enabled) {\ + ctx->Array.ArrayObj->array.EnabledBeforeLock = GL_TRUE; \ +} else ctx->Array.ArrayObj->array.EnabledBeforeLock = GL_FALSE; + ASSERT_OUTSIDE_BEGIN_END_AND_FLUSH(ctx); if (MESA_VERBOSE & VERBOSE_API) @@ -961,8 +966,19 @@ _mesa_LockArraysEXT(GLint first, GLsizei count) ctx->Array.LockFirst = first; ctx->Array.LockCount = count; + UPDATE_ENABLED_BEFORE_LOCK(Vertex); + UPDATE_ENABLED_BEFORE_LOCK(Weight); + UPDATE_ENABLED_BEFORE_LOCK(Normal); + UPDATE_ENABLED_BEFORE_LOCK(Color); + UPDATE_ENABLED_BEFORE_LOCK(SecondaryColor); + UPDATE_ENABLED_BEFORE_LOCK(FogCoord); + UPDATE_ENABLED_BEFORE_LOCK(Index); + UPDATE_ENABLED_BEFORE_LOCK(EdgeFlag); + UPDATE_ENABLED_BEFORE_LOCK(PointSize); + for(int i=0; iNewState |= _NEW_ARRAY; - ctx->Array.NewState |= _NEW_ARRAY_ALL; +// ctx->Array.NewState |= _NEW_ARRAY_ALL; } @@ -983,7 +999,8 @@ _mesa_UnlockArraysEXT( void ) ctx->Array.LockFirst = 0; ctx->Array.LockCount = 0; ctx->NewState |= _NEW_ARRAY; - ctx->Array.NewState |= _NEW_ARRAY_ALL; +// ctx->Array.NewState |= _NEW_ARRAY_ALL; + ctx->Array.NewState = 0; } diff --git a/src/mesa/state_tracker/st_draw.c b/src/mesa/state_tracker/st_draw.c index d27043e..7a4d8f5 100644 --- a/src/mesa/state_tracker/st_draw.c +++ b/src/mesa/state_tracker/st_draw.c @@ -440,6 +440,15 @@ setup_non_interleaved_attribs(struct gl_context *ctx, vbuffer[attr].buffer = pipe_user_buffer_create(pipe->screen, ptr, bytes, PIPE_BIND_VERTEX_BUFFER); + // filling Lock API related fields + if (array->EnabledBeforeLock) { + vbuffer[attr].lock_first = ctx->Array.LockFirst; + vbuffer[attr].lock_count = ctx->Array.LockCount; + vbuffer[attr].flush_lock_cache = (ctx->Array.NewState & (1 << mesaAttr)); + } else { + vbuffer[attr].lock_first = vbuffer[attr].lock_count = 0; + vbuffer[attr].flush_lock_cache = true; + } vbuffer[attr].buffer_offset = 0; @@ -462,6 +471,8 @@ setup_non_interleaved_attribs(struct gl_context *ctx, array->Normalized); assert(velements[attr].src_format); } + + ctx->Array.NewState = 0; } -- 1.7.5.1