Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(77)

Unified Diff: gpu/command_buffer/client/gles2_implementation.cc

Issue 116863003: gpu: Reuse transfer buffers more aggresively (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: [RFC] gpu: Reuse transfer buffers more aggressively Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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 b0efc3769da617acfcc5423f07951c6f8d1dc208..d137473f400fbf894962eab93e0bda8933adac94 100644
--- a/gpu/command_buffer/client/gles2_implementation.cc
+++ b/gpu/command_buffer/client/gles2_implementation.cc
@@ -1379,16 +1379,19 @@ 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);
+ if (buffer->used()) {
+ buffer->set_used(false);
+ buffer->set_unused_token(helper_->InsertToken());
+ }
+ DisposeTransferBuffer(buffer);
}
+ CheckBuffersPendingAsyncComplete();
+
// Create new buffer.
buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
DCHECK(buffer);
+ buffer->set_used(true);
if (buffer->address() && data)
memcpy(buffer->address(), data, size);
return;
@@ -1512,6 +1515,49 @@ void GLES2Implementation::BufferSubData(
CheckGLError();
}
+void GLES2Implementation::FreeTransferBuffer(BufferTracker::Buffer *buffer) {
+ int32 token = buffer->unused_token();
+ // FIXME: This kind of checks exist elsewhere; is it correct?
+ if (token) {
+ if (helper_->HasTokenPassed(token))
piman 2014/01/08 05:08:04 Maybe this logic (if the token is passed, free imm
+ buffer_tracker_->Free(buffer);
+ else
+ buffer_tracker_->FreePendingToken(buffer, token);
+ }
+}
+
+void GLES2Implementation::DisposeTransferBuffer(BufferTracker::Buffer* buffer) {
+ if (buffer->async_query_id()) {
+ QueryTracker::Query* query =
+ query_tracker_->GetQuery(buffer->async_query_id());
+ if (!query->CheckResultsAvailable(helper_)) {
+ // Async upload not completed, queue release.
+ released_buffers_pending_async_complete_.push_back(buffer);
+ buffer_tracker_->UnmanageBuffer(buffer->id());
+ return;
+ }
+ }
+
+ FreeTransferBuffer(buffer);
+ buffer_tracker_->RemoveBuffer(buffer->id());
+}
+
+void GLES2Implementation::CheckBuffersPendingAsyncComplete() {
epennerAtGoogle 2014/01/07 00:47:59 Hmm, it's unfortunate that we have to check all of
reveman 2014/01/07 06:32:06 you could just keep the list sorted based on query
jadahl 2014/01/07 10:52:03 The enumeration will improve this situation indeed
+ BufferList::iterator it = released_buffers_pending_async_complete_.begin();
+ while (it != released_buffers_pending_async_complete_.end()) {
+ BufferTracker::Buffer* buffer = *it;
+ QueryTracker::Query* query =
+ query_tracker_->GetQuery(buffer->async_query_id());
+ if (query->CheckResultsAvailable(helper_)) {
+ it = released_buffers_pending_async_complete_.erase(it);
+ FreeTransferBuffer(buffer);
+ delete buffer;
+ } else {
+ ++it;
+ }
+ }
+}
+
bool GLES2Implementation::GetBoundPixelTransferBuffer(
GLenum target,
const char* function_name,
@@ -2404,24 +2450,42 @@ void GLES2Implementation::GenQueriesEXTHelper(
// deleted the resource.
bool GLES2Implementation::BindBufferHelper(
- GLenum target, GLuint buffer) {
+ GLenum target, GLuint buffer_id) {
+ BufferTracker::Buffer* buffer;
+
// 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;
+ // Mark any previously bound buffer as unused.
+ if (bound_pixel_unpack_transfer_buffer_id_ != buffer_id &&
+ bound_pixel_unpack_transfer_buffer_id_ != 0) {
+ buffer =
+ buffer_tracker_->GetBuffer(bound_pixel_unpack_transfer_buffer_id_);
+ if (buffer) {
+ buffer->set_unused_token(helper_->InsertToken());
+ }
+ }
+
+ bound_pixel_unpack_transfer_buffer_id_ = buffer_id;
+ buffer = buffer_tracker_->GetBuffer(buffer_id);
+ if (buffer) {
+ buffer->set_used(true);
+ buffer->set_unused_token(0);
+ }
+
break;
default:
changed = true;
@@ -2429,7 +2493,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;
}
@@ -2563,13 +2627,14 @@ 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]);
+ buffer->set_used(false);
+ buffer->set_unused_token(helper_->InsertToken());
+ DisposeTransferBuffer(buffer);
}
+
if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
bound_pixel_unpack_transfer_buffer_id_ = 0;
}
@@ -3645,6 +3710,35 @@ GLboolean GLES2Implementation::UnmapBufferCHROMIUM(GLuint target) {
return true;
}
+void GLES2Implementation::BeginQueryAsyncPixelUnpackCompleted(
+ BufferTracker::Buffer *buffer) {
+ DCHECK(!current_private_unpack_query_);
+
+ GLuint id;
+ GetIdHandler(id_namespaces::kQueries)->MakeIds(this, 0, 1, &id);
+ QueryTracker::Query* query =
+ query_tracker_->CreateQuery(
+ id, GL_ASYNC_PIXEL_UNPACK_COMPLETED_PRIVATE_CHROMIUM);
+ if (!query) {
+ MustBeContextLost();
+ return;
+ }
+
+ buffer->set_async_query_id(id);
+ query->Begin(this);
+ CheckGLError();
+
+ current_private_unpack_query_ = query;
+}
+
+void GLES2Implementation::EndQueryAsyncPixelUnpackCompleted() {
+ DCHECK(current_private_unpack_query_);
+
+ current_private_unpack_query_->End(this);
+ current_private_unpack_query_ = NULL;
+ CheckGLError();
+}
+
void GLES2Implementation::AsyncTexImage2DCHROMIUM(
GLenum target, GLint level, GLint internalformat, GLsizei width,
GLsizei height, GLint border, GLenum format, GLenum type,
@@ -3689,9 +3783,11 @@ void GLES2Implementation::AsyncTexImage2DCHROMIUM(
bound_pixel_unpack_transfer_buffer_id_,
"glAsyncTexImage2DCHROMIUM", offset, size);
if (buffer && buffer->shm_id() != -1) {
+ BeginQueryAsyncPixelUnpackCompleted(buffer);
helper_->AsyncTexImage2DCHROMIUM(
target, level, internalformat, width, height, border, format, type,
buffer->shm_id(), buffer->shm_offset() + offset);
+ EndQueryAsyncPixelUnpackCompleted();
}
}
@@ -3733,9 +3829,11 @@ void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
bound_pixel_unpack_transfer_buffer_id_,
"glAsyncTexSubImage2DCHROMIUM", offset, size);
if (buffer && buffer->shm_id() != -1) {
+ BeginQueryAsyncPixelUnpackCompleted(buffer);
helper_->AsyncTexSubImage2DCHROMIUM(
target, level, xoffset, yoffset, width, height, format, type,
buffer->shm_id(), buffer->shm_offset() + offset);
+ EndQueryAsyncPixelUnpackCompleted();
}
}

Powered by Google App Engine
This is Rietveld 408576698