 Chromium Code Reviews
 Chromium Code Reviews Issue 116863003:
  gpu: Reuse transfer buffers more aggresively  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@master
    
  
    Issue 116863003:
  gpu: Reuse transfer buffers more aggresively  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@master| Index: gpu/command_buffer/client/gles2_implementation.cc | 
| diff --git a/gpu/command_buffer/client/gles2_implementation.cc b/gpu/command_buffer/client/gles2_implementation.cc | 
| index 2d02579b116672e26da92edc5e66c7dcc6ae56b8..80e9ee00072df743d0bab3660e5fe96c8c492876 100644 | 
| --- a/gpu/command_buffer/client/gles2_implementation.cc | 
| +++ b/gpu/command_buffer/client/gles2_implementation.cc | 
| @@ -1378,11 +1378,8 @@ void GLES2Implementation::BufferDataHelper( | 
| BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); | 
| if (buffer) { | 
| - // Free buffer memory, pending the passage of a token. | 
| - buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); | 
| - | 
| - // Remove old buffer. | 
| - buffer_tracker_->RemoveBuffer(buffer_id); | 
| + FreeTransferBuffer(buffer); | 
| 
piman
2014/01/16 21:22:50
How does synchronization work wrt asynchronous Rea
 
jadahl
2014/01/17 08:50:25
Hmm. Good point. Reading how readpixels is impleme
 | 
| + buffer_tracker_->RemoveBuffer(buffer->id()); | 
| } | 
| // Create new buffer. | 
| @@ -1511,6 +1508,24 @@ void GLES2Implementation::BufferSubData( | 
| CheckGLError(); | 
| } | 
| +void GLES2Implementation::FreeTransferBuffer(BufferTracker::Buffer* buffer) { | 
| + int32 token = buffer->last_usage_token(); | 
| + | 
| + if (buffer->async_query_id()) { | 
| + QueryTracker::Query* query = | 
| + query_tracker_->GetQuery(buffer->async_query_id()); | 
| + if (!query->CheckResultsAvailable(helper_)) | 
| + buffer_tracker_->FreePendingSerial(buffer, query->serial()); | 
| + else | 
| + buffer_tracker_->Free(buffer); | 
| + } else if (token) { | 
| + if (helper_->HasTokenPassed(token)) | 
| + buffer_tracker_->Free(buffer); | 
| + else | 
| + buffer_tracker_->FreePendingToken(buffer, token); | 
| + } | 
| +} | 
| + | 
| bool GLES2Implementation::GetBoundPixelTransferBuffer( | 
| GLenum target, | 
| const char* function_name, | 
| @@ -1586,7 +1601,7 @@ void GLES2Implementation::CompressedTexImage2D( | 
| helper_->CompressedTexImage2D( | 
| target, level, internalformat, width, height, border, image_size, | 
| buffer->shm_id(), buffer->shm_offset() + offset); | 
| - buffer->set_transfer_ready_token(helper_->InsertToken()); | 
| + MarkPixelTransferBufferLastUsage(buffer); | 
| } | 
| return; | 
| } | 
| @@ -1627,7 +1642,7 @@ void GLES2Implementation::CompressedTexSubImage2D( | 
| helper_->CompressedTexSubImage2D( | 
| target, level, xoffset, yoffset, width, height, format, image_size, | 
| buffer->shm_id(), buffer->shm_offset() + offset); | 
| - buffer->set_transfer_ready_token(helper_->InsertToken()); | 
| + MarkPixelTransferBufferLastUsage(buffer); | 
| CheckGLError(); | 
| } | 
| return; | 
| @@ -1714,7 +1729,7 @@ void GLES2Implementation::TexImage2D( | 
| helper_->TexImage2D( | 
| target, level, internalformat, width, height, border, format, type, | 
| buffer->shm_id(), buffer->shm_offset() + offset); | 
| - buffer->set_transfer_ready_token(helper_->InsertToken()); | 
| + MarkPixelTransferBufferLastUsage(buffer); | 
| CheckGLError(); | 
| } | 
| return; | 
| @@ -1820,7 +1835,7 @@ void GLES2Implementation::TexSubImage2D( | 
| helper_->TexSubImage2D( | 
| target, level, xoffset, yoffset, width, height, format, type, | 
| buffer->shm_id(), buffer->shm_offset() + offset, false); | 
| - buffer->set_transfer_ready_token(helper_->InsertToken()); | 
| + MarkPixelTransferBufferLastUsage(buffer); | 
| CheckGLError(); | 
| } | 
| return; | 
| @@ -2403,24 +2418,24 @@ void GLES2Implementation::GenQueriesEXTHelper( | 
| // deleted the resource. | 
| bool GLES2Implementation::BindBufferHelper( | 
| - GLenum target, GLuint buffer) { | 
| + GLenum target, GLuint buffer_id) { | 
| // TODO(gman): See note #1 above. | 
| bool changed = false; | 
| switch (target) { | 
| case GL_ARRAY_BUFFER: | 
| - if (bound_array_buffer_id_ != buffer) { | 
| - bound_array_buffer_id_ = buffer; | 
| + if (bound_array_buffer_id_ != buffer_id) { | 
| + bound_array_buffer_id_ = buffer_id; | 
| changed = true; | 
| } | 
| break; | 
| case GL_ELEMENT_ARRAY_BUFFER: | 
| - changed = vertex_array_object_manager_->BindElementArray(buffer); | 
| + changed = vertex_array_object_manager_->BindElementArray(buffer_id); | 
| break; | 
| case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: | 
| - bound_pixel_pack_transfer_buffer_id_ = buffer; | 
| + bound_pixel_pack_transfer_buffer_id_ = buffer_id; | 
| break; | 
| case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: | 
| - bound_pixel_unpack_transfer_buffer_id_ = buffer; | 
| + bound_pixel_unpack_transfer_buffer_id_ = buffer_id; | 
| break; | 
| default: | 
| changed = true; | 
| @@ -2428,7 +2443,7 @@ bool GLES2Implementation::BindBufferHelper( | 
| } | 
| // TODO(gman): There's a bug here. If the target is invalid the ID will not be | 
| // used even though it's marked it as used here. | 
| - GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer); | 
| + GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id); | 
| return changed; | 
| } | 
| @@ -2562,13 +2577,13 @@ void GLES2Implementation::DeleteBuffersHelper( | 
| bound_array_buffer_id_ = 0; | 
| } | 
| vertex_array_object_manager_->UnbindBuffer(buffers[ii]); | 
| + | 
| BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); | 
| if (buffer) { | 
| - // Free buffer memory, pending the passage of a token. | 
| - buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); | 
| - // Remove buffer. | 
| - buffer_tracker_->RemoveBuffer(buffers[ii]); | 
| + FreeTransferBuffer(buffer); | 
| + buffer_tracker_->RemoveBuffer(buffer->id()); | 
| } | 
| + | 
| if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { | 
| bound_pixel_unpack_transfer_buffer_id_ = 0; | 
| } | 
| @@ -3288,8 +3303,10 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { | 
| << GLES2Util::GetStringQueryTarget(target) | 
| << ", " << id << ")"); | 
| + QueryKey key = std::make_pair(target, false); | 
| + | 
| // if any outstanding queries INV_OP | 
| - QueryMap::iterator it = current_queries_.find(target); | 
| + QueryMap::iterator it = current_queries_.find(key); | 
| if (it != current_queries_.end()) { | 
| SetGLError( | 
| GL_INVALID_OPERATION, "glBeginQueryEXT", "query already in progress"); | 
| @@ -3318,7 +3335,7 @@ void GLES2Implementation::BeginQueryEXT(GLenum target, GLuint id) { | 
| return; | 
| } | 
| - current_queries_[target] = query; | 
| + current_queries_[key] = query; | 
| query->Begin(this); | 
| CheckGLError(); | 
| @@ -3333,7 +3350,8 @@ void GLES2Implementation::EndQueryEXT(GLenum target) { | 
| return; | 
| } | 
| - QueryMap::iterator it = current_queries_.find(target); | 
| + QueryKey key = std::make_pair(target, false); | 
| + QueryMap::iterator it = current_queries_.find(key); | 
| if (it == current_queries_.end()) { | 
| SetGLError(GL_INVALID_OPERATION, "glEndQueryEXT", "no active query"); | 
| return; | 
| @@ -3357,7 +3375,8 @@ void GLES2Implementation::GetQueryivEXT( | 
| SetGLErrorInvalidEnum("glGetQueryivEXT", pname, "pname"); | 
| return; | 
| } | 
| - QueryMap::iterator it = current_queries_.find(target); | 
| + QueryKey key = std::make_pair(target, false); | 
| + QueryMap::iterator it = current_queries_.find(key); | 
| if (it != current_queries_.end()) { | 
| QueryTracker::Query* query = it->second; | 
| *params = query->id(); | 
| @@ -3381,7 +3400,8 @@ void GLES2Implementation::GetQueryObjectuivEXT( | 
| return; | 
| } | 
| - QueryMap::iterator it = current_queries_.find(query->target()); | 
| + QueryKey key = std::make_pair(query->target(), false); | 
| + QueryMap::iterator it = current_queries_.find(key); | 
| if (it != current_queries_.end()) { | 
| SetGLError( | 
| GL_INVALID_OPERATION, | 
| @@ -3611,9 +3631,9 @@ void* GLES2Implementation::MapBufferCHROMIUM(GLuint target, GLenum access) { | 
| // with this method of synchronization. Until this is fixed, | 
| // MapBufferCHROMIUM will not block even if the transfer is not ready | 
| // for these calls. | 
| - if (buffer->transfer_ready_token()) { | 
| - helper_->WaitForToken(buffer->transfer_ready_token()); | 
| - buffer->set_transfer_ready_token(0); | 
| + if (buffer->last_usage_token()) { | 
| + helper_->WaitForToken(buffer->last_usage_token()); | 
| + buffer->set_last_usage_token(0); | 
| } | 
| buffer->set_mapped(true); | 
| @@ -3647,6 +3667,45 @@ GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) { | 
| return true; | 
| } | 
| +void GLES2Implementation::BeginInternalQueryAsyncPixelUnpackCompleted( | 
| + BufferTracker::Buffer *buffer) { | 
| + QueryKey key = std::make_pair(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, true); | 
| + | 
| + DCHECK(current_queries_.find(key) == current_queries_.end()); | 
| + | 
| + GLuint id; | 
| + GetIdHandler(id_namespaces::kQueries)->MakeIds(this, 0, 1, &id); | 
| + QueryTracker::Query* query = query_tracker_->CreateInternalQuery( | 
| + id, GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM); | 
| + if (!query) { | 
| + MustBeContextLost(); | 
| + return; | 
| + } | 
| + | 
| + buffer->set_async_query_id(id); | 
| + query->Begin(this); | 
| + CheckGLError(); | 
| + | 
| + current_queries_[key] = query; | 
| +} | 
| + | 
| +void GLES2Implementation::EndInternalQueryAsyncPixelUnpackCompleted() { | 
| + QueryKey key = std::make_pair(GL_ASYNC_PIXEL_UNPACK_COMPLETED_CHROMIUM, true); | 
| + | 
| + DCHECK(current_queries_.find(key) != current_queries_.end()); | 
| + | 
| + QueryMap::iterator it = current_queries_.find(key); | 
| + QueryTracker::Query* query = it->second; | 
| + query->End(this); | 
| + current_queries_.erase(it); | 
| + CheckGLError(); | 
| +} | 
| + | 
| +void GLES2Implementation::MarkPixelTransferBufferLastUsage( | 
| + BufferTracker::Buffer* buffer) { | 
| + buffer->set_last_usage_token(helper_->InsertToken()); | 
| +} | 
| + | 
| void GLES2Implementation::AsyncTexImage2DCHROMIUM( | 
| GLenum target, GLint level, GLint internalformat, GLsizei width, | 
| GLsizei height, GLint border, GLenum format, GLenum type, | 
| @@ -3691,9 +3750,11 @@ void GLES2Implementation::AsyncTexImage2DCHROMIUM( | 
| bound_pixel_unpack_transfer_buffer_id_, | 
| "glAsyncTexImage2DCHROMIUM", offset, size); | 
| if (buffer && buffer->shm_id() != -1) { | 
| + BeginInternalQueryAsyncPixelUnpackCompleted(buffer); | 
| helper_->AsyncTexImage2DCHROMIUM( | 
| target, level, internalformat, width, height, border, format, type, | 
| buffer->shm_id(), buffer->shm_offset() + offset); | 
| + EndInternalQueryAsyncPixelUnpackCompleted(); | 
| } | 
| } | 
| @@ -3735,9 +3796,11 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( | 
| bound_pixel_unpack_transfer_buffer_id_, | 
| "glAsyncTexSubImage2DCHROMIUM", offset, size); | 
| if (buffer && buffer->shm_id() != -1) { | 
| + BeginInternalQueryAsyncPixelUnpackCompleted(buffer); | 
| helper_->AsyncTexSubImage2DCHROMIUM( | 
| target, level, xoffset, yoffset, width, height, format, type, | 
| buffer->shm_id(), buffer->shm_offset() + offset); | 
| + EndInternalQueryAsyncPixelUnpackCompleted(); | 
| } | 
| } |