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

Side by Side 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 6 years, 11 months 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 // A class to emulate GLES2 over command buffers. 5 // A class to emulate GLES2 over command buffers.
6 6
7 #include "gpu/command_buffer/client/gles2_implementation.h" 7 #include "gpu/command_buffer/client/gles2_implementation.h"
8 8
9 #include <algorithm> 9 #include <algorithm>
10 #include <map> 10 #include <map>
(...skipping 1361 matching lines...) Expand 10 before | Expand all | Expand 10 after
1372 } 1372 }
1373 1373
1374 GLuint buffer_id; 1374 GLuint buffer_id;
1375 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) { 1375 if (GetBoundPixelTransferBuffer(target, "glBufferData", &buffer_id)) {
1376 if (!buffer_id) { 1376 if (!buffer_id) {
1377 return; 1377 return;
1378 } 1378 }
1379 1379
1380 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id); 1380 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffer_id);
1381 if (buffer) { 1381 if (buffer) {
1382 // Free buffer memory, pending the passage of a token. 1382 if (buffer->used()) {
1383 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); 1383 buffer->set_used(false);
1384 buffer->set_unused_token(helper_->InsertToken());
1385 }
1386 DisposeTransferBuffer(buffer);
1387 }
1384 1388
1385 // Remove old buffer. 1389 CheckBuffersPendingAsyncComplete();
1386 buffer_tracker_->RemoveBuffer(buffer_id);
1387 }
1388 1390
1389 // Create new buffer. 1391 // Create new buffer.
1390 buffer = buffer_tracker_->CreateBuffer(buffer_id, size); 1392 buffer = buffer_tracker_->CreateBuffer(buffer_id, size);
1391 DCHECK(buffer); 1393 DCHECK(buffer);
1394 buffer->set_used(true);
1392 if (buffer->address() && data) 1395 if (buffer->address() && data)
1393 memcpy(buffer->address(), data, size); 1396 memcpy(buffer->address(), data, size);
1394 return; 1397 return;
1395 } 1398 }
1396 1399
1397 if (size == 0) { 1400 if (size == 0) {
1398 return; 1401 return;
1399 } 1402 }
1400 1403
1401 // If there is no data just send BufferData 1404 // If there is no data just send BufferData
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
1505 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) { 1508 GLenum target, GLintptr offset, GLsizeiptr size, const void* data) {
1506 GPU_CLIENT_SINGLE_THREAD_CHECK(); 1509 GPU_CLIENT_SINGLE_THREAD_CHECK();
1507 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData(" 1510 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glBufferSubData("
1508 << GLES2Util::GetStringBufferTarget(target) << ", " 1511 << GLES2Util::GetStringBufferTarget(target) << ", "
1509 << offset << ", " << size << ", " 1512 << offset << ", " << size << ", "
1510 << static_cast<const void*>(data) << ")"); 1513 << static_cast<const void*>(data) << ")");
1511 BufferSubDataHelper(target, offset, size, data); 1514 BufferSubDataHelper(target, offset, size, data);
1512 CheckGLError(); 1515 CheckGLError();
1513 } 1516 }
1514 1517
1518 void GLES2Implementation::FreeTransferBuffer(BufferTracker::Buffer *buffer) {
1519 int32 token = buffer->unused_token();
1520 // FIXME: This kind of checks exist elsewhere; is it correct?
1521 if (token) {
1522 if (helper_->HasTokenPassed(token))
piman 2014/01/08 05:08:04 Maybe this logic (if the token is passed, free imm
1523 buffer_tracker_->Free(buffer);
1524 else
1525 buffer_tracker_->FreePendingToken(buffer, token);
1526 }
1527 }
1528
1529 void GLES2Implementation::DisposeTransferBuffer(BufferTracker::Buffer* buffer) {
1530 if (buffer->async_query_id()) {
1531 QueryTracker::Query* query =
1532 query_tracker_->GetQuery(buffer->async_query_id());
1533 if (!query->CheckResultsAvailable(helper_)) {
1534 // Async upload not completed, queue release.
1535 released_buffers_pending_async_complete_.push_back(buffer);
1536 buffer_tracker_->UnmanageBuffer(buffer->id());
1537 return;
1538 }
1539 }
1540
1541 FreeTransferBuffer(buffer);
1542 buffer_tracker_->RemoveBuffer(buffer->id());
1543 }
1544
1545 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
1546 BufferList::iterator it = released_buffers_pending_async_complete_.begin();
1547 while (it != released_buffers_pending_async_complete_.end()) {
1548 BufferTracker::Buffer* buffer = *it;
1549 QueryTracker::Query* query =
1550 query_tracker_->GetQuery(buffer->async_query_id());
1551 if (query->CheckResultsAvailable(helper_)) {
1552 it = released_buffers_pending_async_complete_.erase(it);
1553 FreeTransferBuffer(buffer);
1554 delete buffer;
1555 } else {
1556 ++it;
1557 }
1558 }
1559 }
1560
1515 bool GLES2Implementation::GetBoundPixelTransferBuffer( 1561 bool GLES2Implementation::GetBoundPixelTransferBuffer(
1516 GLenum target, 1562 GLenum target,
1517 const char* function_name, 1563 const char* function_name,
1518 GLuint* buffer_id) { 1564 GLuint* buffer_id) {
1519 *buffer_id = 0; 1565 *buffer_id = 0;
1520 1566
1521 switch (target) { 1567 switch (target) {
1522 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 1568 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
1523 *buffer_id = bound_pixel_pack_transfer_buffer_id_; 1569 *buffer_id = bound_pixel_pack_transfer_buffer_id_;
1524 break; 1570 break;
(...skipping 872 matching lines...) Expand 10 before | Expand all | Expand 10 after
2397 } 2443 }
2398 2444
2399 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id 2445 // NOTE #1: On old versions of OpenGL, calling glBindXXX with an unused id
2400 // generates a new resource. On newer versions of OpenGL they don't. The code 2446 // generates a new resource. On newer versions of OpenGL they don't. The code
2401 // related to binding below will need to change if we switch to the new OpenGL 2447 // related to binding below will need to change if we switch to the new OpenGL
2402 // model. Specifically it assumes a bind will succeed which is always true in 2448 // model. Specifically it assumes a bind will succeed which is always true in
2403 // the old model but possibly not true in the new model if another context has 2449 // the old model but possibly not true in the new model if another context has
2404 // deleted the resource. 2450 // deleted the resource.
2405 2451
2406 bool GLES2Implementation::BindBufferHelper( 2452 bool GLES2Implementation::BindBufferHelper(
2407 GLenum target, GLuint buffer) { 2453 GLenum target, GLuint buffer_id) {
2454 BufferTracker::Buffer* buffer;
2455
2408 // TODO(gman): See note #1 above. 2456 // TODO(gman): See note #1 above.
2409 bool changed = false; 2457 bool changed = false;
2410 switch (target) { 2458 switch (target) {
2411 case GL_ARRAY_BUFFER: 2459 case GL_ARRAY_BUFFER:
2412 if (bound_array_buffer_id_ != buffer) { 2460 if (bound_array_buffer_id_ != buffer_id) {
2413 bound_array_buffer_id_ = buffer; 2461 bound_array_buffer_id_ = buffer_id;
2414 changed = true; 2462 changed = true;
2415 } 2463 }
2416 break; 2464 break;
2417 case GL_ELEMENT_ARRAY_BUFFER: 2465 case GL_ELEMENT_ARRAY_BUFFER:
2418 changed = vertex_array_object_manager_->BindElementArray(buffer); 2466 changed = vertex_array_object_manager_->BindElementArray(buffer_id);
2419 break; 2467 break;
2420 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM: 2468 case GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM:
2421 bound_pixel_pack_transfer_buffer_id_ = buffer; 2469 bound_pixel_pack_transfer_buffer_id_ = buffer_id;
2422 break; 2470 break;
2423 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM: 2471 case GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM:
2424 bound_pixel_unpack_transfer_buffer_id_ = buffer; 2472 // Mark any previously bound buffer as unused.
2473 if (bound_pixel_unpack_transfer_buffer_id_ != buffer_id &&
2474 bound_pixel_unpack_transfer_buffer_id_ != 0) {
2475 buffer =
2476 buffer_tracker_->GetBuffer(bound_pixel_unpack_transfer_buffer_id_);
2477 if (buffer) {
2478 buffer->set_unused_token(helper_->InsertToken());
2479 }
2480 }
2481
2482 bound_pixel_unpack_transfer_buffer_id_ = buffer_id;
2483 buffer = buffer_tracker_->GetBuffer(buffer_id);
2484 if (buffer) {
2485 buffer->set_used(true);
2486 buffer->set_unused_token(0);
2487 }
2488
2425 break; 2489 break;
2426 default: 2490 default:
2427 changed = true; 2491 changed = true;
2428 break; 2492 break;
2429 } 2493 }
2430 // TODO(gman): There's a bug here. If the target is invalid the ID will not be 2494 // TODO(gman): There's a bug here. If the target is invalid the ID will not be
2431 // used even though it's marked it as used here. 2495 // used even though it's marked it as used here.
2432 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer); 2496 GetIdHandler(id_namespaces::kBuffers)->MarkAsUsedForBind(buffer_id);
2433 return changed; 2497 return changed;
2434 } 2498 }
2435 2499
2436 bool GLES2Implementation::BindFramebufferHelper( 2500 bool GLES2Implementation::BindFramebufferHelper(
2437 GLenum target, GLuint framebuffer) { 2501 GLenum target, GLuint framebuffer) {
2438 // TODO(gman): See note #1 above. 2502 // TODO(gman): See note #1 above.
2439 bool changed = false; 2503 bool changed = false;
2440 switch (target) { 2504 switch (target) {
2441 case GL_FRAMEBUFFER: 2505 case GL_FRAMEBUFFER:
2442 if (bound_framebuffer_ != framebuffer || 2506 if (bound_framebuffer_ != framebuffer ||
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
2556 SetGLError( 2620 SetGLError(
2557 GL_INVALID_VALUE, 2621 GL_INVALID_VALUE,
2558 "glDeleteBuffers", "id not created by this context."); 2622 "glDeleteBuffers", "id not created by this context.");
2559 return; 2623 return;
2560 } 2624 }
2561 for (GLsizei ii = 0; ii < n; ++ii) { 2625 for (GLsizei ii = 0; ii < n; ++ii) {
2562 if (buffers[ii] == bound_array_buffer_id_) { 2626 if (buffers[ii] == bound_array_buffer_id_) {
2563 bound_array_buffer_id_ = 0; 2627 bound_array_buffer_id_ = 0;
2564 } 2628 }
2565 vertex_array_object_manager_->UnbindBuffer(buffers[ii]); 2629 vertex_array_object_manager_->UnbindBuffer(buffers[ii]);
2630
2566 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]); 2631 BufferTracker::Buffer* buffer = buffer_tracker_->GetBuffer(buffers[ii]);
2567 if (buffer) { 2632 if (buffer) {
2568 // Free buffer memory, pending the passage of a token. 2633 buffer->set_used(false);
2569 buffer_tracker_->FreePendingToken(buffer, helper_->InsertToken()); 2634 buffer->set_unused_token(helper_->InsertToken());
2570 // Remove buffer. 2635 DisposeTransferBuffer(buffer);
2571 buffer_tracker_->RemoveBuffer(buffers[ii]);
2572 } 2636 }
2637
2573 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) { 2638 if (buffers[ii] == bound_pixel_unpack_transfer_buffer_id_) {
2574 bound_pixel_unpack_transfer_buffer_id_ = 0; 2639 bound_pixel_unpack_transfer_buffer_id_ = 0;
2575 } 2640 }
2576 } 2641 }
2577 } 2642 }
2578 2643
2579 void GLES2Implementation::DeleteBuffersStub( 2644 void GLES2Implementation::DeleteBuffersStub(
2580 GLsizei n, const GLuint* buffers) { 2645 GLsizei n, const GLuint* buffers) {
2581 helper_->DeleteBuffersImmediate(n, buffers); 2646 helper_->DeleteBuffersImmediate(n, buffers);
2582 } 2647 }
(...skipping 1055 matching lines...) Expand 10 before | Expand all | Expand 10 after
3638 } 3703 }
3639 if (!buffer->mapped()) { 3704 if (!buffer->mapped()) {
3640 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped"); 3705 SetGLError(GL_INVALID_OPERATION, "glUnmapBufferCHROMIUM", "not mapped");
3641 return false; 3706 return false;
3642 } 3707 }
3643 buffer->set_mapped(false); 3708 buffer->set_mapped(false);
3644 CheckGLError(); 3709 CheckGLError();
3645 return true; 3710 return true;
3646 } 3711 }
3647 3712
3713 void GLES2Implementation::BeginQueryAsyncPixelUnpackCompleted(
3714 BufferTracker::Buffer *buffer) {
3715 DCHECK(!current_private_unpack_query_);
3716
3717 GLuint id;
3718 GetIdHandler(id_namespaces::kQueries)->MakeIds(this, 0, 1, &id);
3719 QueryTracker::Query* query =
3720 query_tracker_->CreateQuery(
3721 id, GL_ASYNC_PIXEL_UNPACK_COMPLETED_PRIVATE_CHROMIUM);
3722 if (!query) {
3723 MustBeContextLost();
3724 return;
3725 }
3726
3727 buffer->set_async_query_id(id);
3728 query->Begin(this);
3729 CheckGLError();
3730
3731 current_private_unpack_query_ = query;
3732 }
3733
3734 void GLES2Implementation::EndQueryAsyncPixelUnpackCompleted() {
3735 DCHECK(current_private_unpack_query_);
3736
3737 current_private_unpack_query_->End(this);
3738 current_private_unpack_query_ = NULL;
3739 CheckGLError();
3740 }
3741
3648 void GLES2Implementation::AsyncTexImage2DCHROMIUM( 3742 void GLES2Implementation::AsyncTexImage2DCHROMIUM(
3649 GLenum target, GLint level, GLint internalformat, GLsizei width, 3743 GLenum target, GLint level, GLint internalformat, GLsizei width,
3650 GLsizei height, GLint border, GLenum format, GLenum type, 3744 GLsizei height, GLint border, GLenum format, GLenum type,
3651 const void* pixels) { 3745 const void* pixels) {
3652 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3746 GPU_CLIENT_SINGLE_THREAD_CHECK();
3653 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D(" 3747 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glTexImage2D("
3654 << GLES2Util::GetStringTextureTarget(target) << ", " 3748 << GLES2Util::GetStringTextureTarget(target) << ", "
3655 << level << ", " 3749 << level << ", "
3656 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", " 3750 << GLES2Util::GetStringTextureInternalFormat(internalformat) << ", "
3657 << width << ", " << height << ", " << border << ", " 3751 << width << ", " << height << ", " << border << ", "
(...skipping 24 matching lines...) Expand all
3682 3776
3683 // Otherwise, async uploads require a transfer buffer to be bound. 3777 // Otherwise, async uploads require a transfer buffer to be bound.
3684 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3778 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3685 // the buffer before the transfer is finished. (Currently such 3779 // the buffer before the transfer is finished. (Currently such
3686 // synchronization has to be handled manually.) 3780 // synchronization has to be handled manually.)
3687 GLuint offset = ToGLuint(pixels); 3781 GLuint offset = ToGLuint(pixels);
3688 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3782 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
3689 bound_pixel_unpack_transfer_buffer_id_, 3783 bound_pixel_unpack_transfer_buffer_id_,
3690 "glAsyncTexImage2DCHROMIUM", offset, size); 3784 "glAsyncTexImage2DCHROMIUM", offset, size);
3691 if (buffer && buffer->shm_id() != -1) { 3785 if (buffer && buffer->shm_id() != -1) {
3786 BeginQueryAsyncPixelUnpackCompleted(buffer);
3692 helper_->AsyncTexImage2DCHROMIUM( 3787 helper_->AsyncTexImage2DCHROMIUM(
3693 target, level, internalformat, width, height, border, format, type, 3788 target, level, internalformat, width, height, border, format, type,
3694 buffer->shm_id(), buffer->shm_offset() + offset); 3789 buffer->shm_id(), buffer->shm_offset() + offset);
3790 EndQueryAsyncPixelUnpackCompleted();
3695 } 3791 }
3696 } 3792 }
3697 3793
3698 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM( 3794 void GLES2Implementation::AsyncTexSubImage2DCHROMIUM(
3699 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, 3795 GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width,
3700 GLsizei height, GLenum format, GLenum type, const void* pixels) { 3796 GLsizei height, GLenum format, GLenum type, const void* pixels) {
3701 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3797 GPU_CLIENT_SINGLE_THREAD_CHECK();
3702 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM(" 3798 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glAsyncTexSubImage2DCHROMIUM("
3703 << GLES2Util::GetStringTextureTarget(target) << ", " 3799 << GLES2Util::GetStringTextureTarget(target) << ", "
3704 << level << ", " 3800 << level << ", "
(...skipping 21 matching lines...) Expand all
3726 3822
3727 // Async uploads require a transfer buffer to be bound. 3823 // Async uploads require a transfer buffer to be bound.
3728 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use 3824 // TODO(hubbe): Make MapBufferCHROMIUM block if someone tries to re-use
3729 // the buffer before the transfer is finished. (Currently such 3825 // the buffer before the transfer is finished. (Currently such
3730 // synchronization has to be handled manually.) 3826 // synchronization has to be handled manually.)
3731 GLuint offset = ToGLuint(pixels); 3827 GLuint offset = ToGLuint(pixels);
3732 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid( 3828 BufferTracker::Buffer* buffer = GetBoundPixelUnpackTransferBufferIfValid(
3733 bound_pixel_unpack_transfer_buffer_id_, 3829 bound_pixel_unpack_transfer_buffer_id_,
3734 "glAsyncTexSubImage2DCHROMIUM", offset, size); 3830 "glAsyncTexSubImage2DCHROMIUM", offset, size);
3735 if (buffer && buffer->shm_id() != -1) { 3831 if (buffer && buffer->shm_id() != -1) {
3832 BeginQueryAsyncPixelUnpackCompleted(buffer);
3736 helper_->AsyncTexSubImage2DCHROMIUM( 3833 helper_->AsyncTexSubImage2DCHROMIUM(
3737 target, level, xoffset, yoffset, width, height, format, type, 3834 target, level, xoffset, yoffset, width, height, format, type,
3738 buffer->shm_id(), buffer->shm_offset() + offset); 3835 buffer->shm_id(), buffer->shm_offset() + offset);
3836 EndQueryAsyncPixelUnpackCompleted();
3739 } 3837 }
3740 } 3838 }
3741 3839
3742 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) { 3840 void GLES2Implementation::WaitAsyncTexImage2DCHROMIUM(GLenum target) {
3743 GPU_CLIENT_SINGLE_THREAD_CHECK(); 3841 GPU_CLIENT_SINGLE_THREAD_CHECK();
3744 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM(" 3842 GPU_CLIENT_LOG("[" << GetLogPrefix() << "] glWaitAsyncTexImage2DCHROMIUM("
3745 << GLES2Util::GetStringTextureTarget(target) << ")"); 3843 << GLES2Util::GetStringTextureTarget(target) << ")");
3746 helper_->WaitAsyncTexImage2DCHROMIUM(target); 3844 helper_->WaitAsyncTexImage2DCHROMIUM(target);
3747 CheckGLError(); 3845 CheckGLError();
3748 } 3846 }
(...skipping 166 matching lines...) Expand 10 before | Expand all | Expand 10 after
3915 CheckGLError(); 4013 CheckGLError();
3916 } 4014 }
3917 4015
3918 // Include the auto-generated part of this file. We split this because it means 4016 // Include the auto-generated part of this file. We split this because it means
3919 // we can easily edit the non-auto generated parts right here in this file 4017 // we can easily edit the non-auto generated parts right here in this file
3920 // instead of having to edit some template or the code generator. 4018 // instead of having to edit some template or the code generator.
3921 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h" 4019 #include "gpu/command_buffer/client/gles2_implementation_impl_autogen.h"
3922 4020
3923 } // namespace gles2 4021 } // namespace gles2
3924 } // namespace gpu 4022 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698