 Chromium Code Reviews
 Chromium Code Reviews Issue 10916292:
  Adaptively throttle texture uploads  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@master
    
  
    Issue 10916292:
  Adaptively throttle texture uploads  (Closed) 
  Base URL: http://git.chromium.org/chromium/src.git@master| Index: cc/ThrottledTextureUploader.cpp | 
| diff --git a/cc/ThrottledTextureUploader.cpp b/cc/ThrottledTextureUploader.cpp | 
| index 594342e54ec96873a141c2aad5535ea7a3e62894..410b0ca3a7bcefccc6bb1d93004f9691a00bd27a 100644 | 
| --- a/cc/ThrottledTextureUploader.cpp | 
| +++ b/cc/ThrottledTextureUploader.cpp | 
| @@ -3,10 +3,10 @@ | 
| // found in the LICENSE file. | 
| #include "config.h" | 
| - | 
| #include "ThrottledTextureUploader.h" | 
| #include "Extensions3DChromium.h" | 
| +#include <algorithm> | 
| #include <public/WebGraphicsContext3D.h> | 
| namespace { | 
| @@ -14,6 +14,12 @@ namespace { | 
| // Number of pending texture update queries to allow. | 
| static const size_t maxPendingQueries = 2; | 
| +// How many previous uploads to use when predicting future throughput. | 
| +static const size_t uploadHistorySize = 10; | 
| 
nduca
2012/09/14 05:50:26
This is in number of queries, right? I might make
 
brianderson
2012/09/14 19:12:00
I intentionally kept it low so that we would quick
 | 
| + | 
| +// Default number of pixels per second. | 
| 
nduca
2012/09/14 05:50:26
This seems a bit low, no? If you have 1.5ms per te
 
brianderson
2012/09/14 19:12:00
It is low.  What I've calculated below is actually
 | 
| +static double estimatedPixelsPerSecondDefault = 256 * 256 * 48; | 
| + | 
| } // anonymous namespace | 
| namespace WebCore { | 
| @@ -21,6 +27,7 @@ namespace WebCore { | 
| ThrottledTextureUploader::Query::Query(WebKit::WebGraphicsContext3D* context) | 
| : m_context(context) | 
| , m_queryId(0) | 
| + , m_pixelsUploaded(0) | 
| { | 
| m_queryId = m_context->createQueryEXT(); | 
| } | 
| @@ -35,9 +42,10 @@ void ThrottledTextureUploader::Query::begin() | 
| m_context->beginQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM, m_queryId); | 
| } | 
| -void ThrottledTextureUploader::Query::end() | 
| +void ThrottledTextureUploader::Query::end(double pixelsUploaded) | 
| { | 
| m_context->endQueryEXT(Extensions3DChromium::COMMANDS_ISSUED_CHROMIUM); | 
| + m_pixelsUploaded = pixelsUploaded; | 
| } | 
| bool ThrottledTextureUploader::Query::isPending() | 
| @@ -49,19 +57,33 @@ bool ThrottledTextureUploader::Query::isPending() | 
| void ThrottledTextureUploader::Query::wait() | 
| { | 
| + value(); | 
| + return; | 
| +} | 
| + | 
| +unsigned ThrottledTextureUploader::Query::value() | 
| +{ | 
| 
nduca
2012/09/14 05:50:26
can you reverse this so that you have m_hasValue,
 
brianderson
2012/09/14 19:12:00
Ok. Avoiding the call to getQueryObjectuivEXT mult
 | 
| unsigned result; | 
| m_context->getQueryObjectuivEXT(m_queryId, Extensions3DChromium::QUERY_RESULT_EXT, &result); | 
| + return result; | 
| +} | 
| + | 
| +double ThrottledTextureUploader::Query::pixelsUploaded() | 
| +{ | 
| + return m_pixelsUploaded; | 
| } | 
| ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context) | 
| : m_context(context) | 
| , m_maxPendingQueries(maxPendingQueries) | 
| + , m_pixelsUploaded(0) | 
| { | 
| } | 
| ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* context, size_t pendingUploadLimit) | 
| : m_context(context) | 
| , m_maxPendingQueries(pendingUploadLimit) | 
| + , m_pixelsUploaded(0) | 
| { | 
| ASSERT(m_context); | 
| } | 
| @@ -69,7 +91,6 @@ ThrottledTextureUploader::ThrottledTextureUploader(WebKit::WebGraphicsContext3D* | 
| ThrottledTextureUploader::~ThrottledTextureUploader() | 
| { | 
| } | 
| - | 
| bool ThrottledTextureUploader::isBusy() | 
| { | 
| processQueries(); | 
| @@ -84,8 +105,23 @@ bool ThrottledTextureUploader::isBusy() | 
| return false; | 
| } | 
| +double ThrottledTextureUploader::estimatedPixelsPerSecond() | 
| +{ | 
| + processQueries(); | 
| + | 
| + if (m_pixelsPerSecondHistory.empty()) | 
| 
nduca
2012/09/14 05:50:26
Instead of this, seed the queue with max entries w
 
brianderson
2012/09/14 19:12:00
Sounds good.
 | 
| + return estimatedPixelsPerSecondDefault; | 
| + | 
| + // Sort the history and use the median as our estimate. | 
| + std::deque<double> sortedHistory(m_pixelsPerSecondHistory); | 
| 
nduca
2012/09/14 05:50:26
why deque and not a vector?
 
brianderson
2012/09/14 19:12:00
My thinking was that the deque copy constructor wo
 | 
| + std::sort(sortedHistory.begin(), sortedHistory.end()); | 
| + return sortedHistory[sortedHistory.size() / 2]; | 
| +} | 
| + | 
| void ThrottledTextureUploader::beginUploads() | 
| { | 
| + m_pixelsUploaded = 0; | 
| + | 
| // Wait for query to become available. | 
| while (isBusy()) | 
| m_pendingQueries.first()->wait(); | 
| @@ -96,12 +132,13 @@ void ThrottledTextureUploader::beginUploads() | 
| void ThrottledTextureUploader::endUploads() | 
| { | 
| - m_availableQueries.first()->end(); | 
| + m_availableQueries.first()->end(m_pixelsUploaded); | 
| m_pendingQueries.append(m_availableQueries.takeFirst()); | 
| } | 
| void ThrottledTextureUploader::uploadTexture(CCResourceProvider* resourceProvider, Parameters upload) | 
| { | 
| + m_pixelsUploaded += upload.sourceRect.width() * upload.sourceRect.width(); | 
| upload.texture->updateRect(resourceProvider, upload.sourceRect, upload.destOffset); | 
| } | 
| @@ -111,6 +148,14 @@ void ThrottledTextureUploader::processQueries() | 
| if (m_pendingQueries.first()->isPending()) | 
| break; | 
| + unsigned usElapsed = m_pendingQueries.first()->value(); | 
| + double pixelsPerSecond = m_pendingQueries.first()->pixelsUploaded() / (usElapsed * 1e-6); | 
| + | 
| + // Remove the oldest values from our history and insert the new one | 
| + if (m_pixelsPerSecondHistory.size() >= uploadHistorySize) | 
| + m_pixelsPerSecondHistory.pop_back(); | 
| + m_pixelsPerSecondHistory.push_front(pixelsPerSecond); | 
| + | 
| m_availableQueries.append(m_pendingQueries.takeFirst()); | 
| } | 
| } |