aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar robertphillips <robertphillips@google.com>2014-08-18 08:50:03 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2014-08-18 08:50:03 -0700
commit6f294af43bcd94ed9616a7e4f5892589813d0a01 (patch)
tree0be9696ceeb7c5ad6a160fe58aa1c1b6d15772a6
parent479601b9a74b5b8e424ed3d68882e161617bdceb (diff)
Refactor GrLayerCache for new API
The only substantive change in this CL is skipping atlasing for any layers that are involved in nesting. Prior versions have allowed nesting layers to be atlased. -------------------------------------------------------- All times are on Windows with a repeat count of 200. Format is: <time in ms> (<# of glBindframebuffer calls>) How to interpret this: For the boogie page: both columns should be the same (since boogie has no nested layers) without the new API the tiled case doesn't show any real benefit from hoisting For the carsvg page: The nesting change does increase the number of FBO switches but doesn't kill performance Because of the location & size of the layers the tile case does show some improvement (even without the new API) boogie ------- w/o nested change w/ nested change simple 5.62 (811) N/A tiled 7.72 (811) N/A simple w/ hoisting 5.23 (409) 5.77 (409) (but no caching) tiled w/ hoisting 7.57 (809) 7.49 (809) (but no caching) carsvg ------ w/o nested change w/ nested change simple 60.37 (141990) N/A tiled 115.13 (256929) N/A simple w/ hoisting 41.57 (64570) 42.82 (72279) (but no caching) tiled w/ hoisting 84.24 (154352) 84.71 (165630) (but no caching) R=bsalomon@google.com Author: robertphillips@google.com Review URL: https://codereview.chromium.org/476833004
-rw-r--r--src/gpu/GrLayerCache.cpp105
-rw-r--r--src/gpu/GrLayerCache.h24
-rw-r--r--src/gpu/SkGpuDevice.cpp16
-rw-r--r--tests/GpuLayerCacheTest.cpp22
4 files changed, 101 insertions, 66 deletions
diff --git a/src/gpu/GrLayerCache.cpp b/src/gpu/GrLayerCache.cpp
index 5fb76d7392..c0510c0365 100644
--- a/src/gpu/GrLayerCache.cpp
+++ b/src/gpu/GrLayerCache.cpp
@@ -117,37 +117,36 @@ void GrLayerCache::freeAll() {
this->initAtlas();
}
-GrCachedLayer* GrLayerCache::createLayer(const SkPicture* picture,
+GrCachedLayer* GrLayerCache::createLayer(uint32_t pictureID,
int start, int stop,
const SkMatrix& ctm) {
- SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0);
+ SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0);
- GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (picture->uniqueID(), start, stop, ctm));
+ GrCachedLayer* layer = SkNEW_ARGS(GrCachedLayer, (pictureID, start, stop, ctm));
fLayerHash.add(layer);
return layer;
}
-GrCachedLayer* GrLayerCache::findLayer(const SkPicture* picture,
+GrCachedLayer* GrLayerCache::findLayer(uint32_t pictureID,
int start, int stop,
const SkMatrix& ctm) {
- SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0);
- return fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(), start, stop, ctm));
+ SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0);
+ return fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, ctm));
}
-GrCachedLayer* GrLayerCache::findLayerOrCreate(const SkPicture* picture,
+GrCachedLayer* GrLayerCache::findLayerOrCreate(uint32_t pictureID,
int start, int stop,
const SkMatrix& ctm) {
- SkASSERT(picture->uniqueID() != SK_InvalidGenID && start > 0 && stop > 0);
- GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(picture->uniqueID(),
- start, stop, ctm));
+ SkASSERT(pictureID != SK_InvalidGenID && start > 0 && stop > 0);
+ GrCachedLayer* layer = fLayerHash.find(GrCachedLayer::Key(pictureID, start, stop, ctm));
if (NULL == layer) {
- layer = this->createLayer(picture, start, stop, ctm);
+ layer = this->createLayer(pictureID, start, stop, ctm);
}
return layer;
}
-bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) {
+bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool dontAtlas) {
SkDEBUGCODE(GrAutoValidateLayer avl(fAtlas->getTexture(), layer);)
if (layer->locked()) {
@@ -155,19 +154,21 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) {
#ifdef SK_DEBUG
if (layer->isAtlased()) {
// It claims to be atlased
+ SkASSERT(!dontAtlas);
SkASSERT(layer->rect().width() == desc.fWidth);
SkASSERT(layer->rect().height() == desc.fHeight);
}
#endif
- return true;
+ return false;
}
if (layer->isAtlased()) {
// Hooray it is still in the atlas - make sure it stays there
+ SkASSERT(!dontAtlas);
layer->setLocked(true);
fPlotLocks[layer->plot()->id()]++;
- return true;
- } else if (PlausiblyAtlasable(desc.fWidth, desc.fHeight)) {
+ return false;
+ } else if (!dontAtlas && PlausiblyAtlasable(desc.fWidth, desc.fHeight)) {
// Not in the atlas - will it fit?
GrPictureInfo* pictInfo = fPictureHash.find(layer->pictureID());
if (NULL == pictInfo) {
@@ -185,13 +186,13 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) {
if (NULL != plot) {
// The layer was successfully added to the atlas
GrIRect16 bounds = GrIRect16::MakeXYWH(loc.fX, loc.fY,
- SkToS16(desc.fWidth),
+ SkToS16(desc.fWidth),
SkToS16(desc.fHeight));
layer->setTexture(fAtlas->getTexture(), bounds);
layer->setPlot(plot);
layer->setLocked(true);
fPlotLocks[layer->plot()->id()]++;
- return false;
+ return true;
}
// The layer was rejected by the atlas (even though we know it is
@@ -210,7 +211,7 @@ bool GrLayerCache::lock(GrCachedLayer* layer, const GrTextureDesc& desc) {
layer->setTexture(tex, GrIRect16::MakeWH(SkToS16(desc.fWidth), SkToS16(desc.fHeight)));
layer->setLocked(true);
- return false;
+ return true;
}
void GrLayerCache::unlock(GrCachedLayer* layer) {
@@ -228,7 +229,7 @@ void GrLayerCache::unlock(GrCachedLayer* layer) {
fPlotLocks[plotID]--;
// At this point we could aggressively clear out un-locked plots but
// by delaying we may be able to reuse some of the atlased layers later.
-#if 0
+#if DISABLE_CACHING
// This testing code aggressively removes the atlased layers. This
// can be used to separate the performance contribution of less
// render target pingponging from that due to the re-use of cached layers
@@ -264,7 +265,9 @@ void GrLayerCache::validate() const {
if (NULL != pictInfo) {
// In aggressive cleanup mode a picture info should only exist if
// it has some atlased layers
+#if !DISABLE_CACHING
SkASSERT(!pictInfo->fPlotUsage.isEmpty());
+#endif
} else {
// If there is no picture info for this layer then all of its
// layers should be non-atlased.
@@ -341,39 +344,57 @@ bool GrLayerCache::purgePlot() {
continue;
}
- // We need to find all the layers in 'plot' and remove them.
- SkTDArray<GrCachedLayer*> toBeRemoved;
+ this->purgePlot(plot);
+ return true;
+ }
- SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash);
- for (; !iter.done(); ++iter) {
- if (plot == (*iter).plot()) {
- *toBeRemoved.append() = &(*iter);
- }
+ return false;
+}
+
+void GrLayerCache::purgePlot(GrPlot* plot) {
+ SkASSERT(0 == fPlotLocks[plot->id()]);
+
+ // We need to find all the layers in 'plot' and remove them.
+ SkTDArray<GrCachedLayer*> toBeRemoved;
+
+ SkTDynamicHash<GrCachedLayer, GrCachedLayer::Key>::Iter iter(&fLayerHash);
+ for (; !iter.done(); ++iter) {
+ if (plot == (*iter).plot()) {
+ *toBeRemoved.append() = &(*iter);
}
+ }
- for (int i = 0; i < toBeRemoved.count(); ++i) {
- SkASSERT(!toBeRemoved[i]->locked());
+ for (int i = 0; i < toBeRemoved.count(); ++i) {
+ SkASSERT(!toBeRemoved[i]->locked());
- GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID());
- SkASSERT(NULL != pictInfo);
+ GrPictureInfo* pictInfo = fPictureHash.find(toBeRemoved[i]->pictureID());
+ SkASSERT(NULL != pictInfo);
- GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot);
+ GrAtlas::RemovePlot(&pictInfo->fPlotUsage, plot);
- // Aggressively remove layers and, if now totally uncached, picture info
- fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i]));
- SkDELETE(toBeRemoved[i]);
+ // Aggressively remove layers and, if now totally uncached, picture info
+ fLayerHash.remove(GrCachedLayer::GetKey(*toBeRemoved[i]));
+ SkDELETE(toBeRemoved[i]);
- if (pictInfo->fPlotUsage.isEmpty()) {
- fPictureHash.remove(pictInfo->fPictureID);
- SkDELETE(pictInfo);
- }
+ if (pictInfo->fPlotUsage.isEmpty()) {
+ fPictureHash.remove(pictInfo->fPictureID);
+ SkDELETE(pictInfo);
}
-
- plot->resetRects();
- return true;
}
- return false;
+ plot->resetRects();
+}
+
+void GrLayerCache::purgeAll() {
+ GrAtlas::PlotIter iter;
+ GrPlot* plot;
+ for (plot = fAtlas->iterInit(&iter, GrAtlas::kLRUFirst_IterOrder);
+ NULL != plot;
+ plot = iter.prev()) {
+ SkASSERT(0 == fPlotLocks[plot->id()]);
+
+ this->purgePlot(plot);
+ }
}
class GrPictureDeletionListener : public SkPicture::DeletionListener {
diff --git a/src/gpu/GrLayerCache.h b/src/gpu/GrLayerCache.h
index f027a26cbc..fcf62f9c3a 100644
--- a/src/gpu/GrLayerCache.h
+++ b/src/gpu/GrLayerCache.h
@@ -117,7 +117,7 @@ public:
const GrIRect16& rect() const { return fRect; }
void setPlot(GrPlot* plot) {
- SkASSERT(NULL == fPlot);
+ SkASSERT(NULL == plot || NULL == fPlot);
fPlot = plot;
}
GrPlot* plot() { return fPlot; }
@@ -171,16 +171,15 @@ public:
// elements by the GrContext
void freeAll();
- GrCachedLayer* findLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm);
- GrCachedLayer* findLayerOrCreate(const SkPicture* picture,
+ GrCachedLayer* findLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm);
+ GrCachedLayer* findLayerOrCreate(uint32_t pictureID,
int start, int stop,
const SkMatrix& ctm);
-
- // Inform the cache that layer's cached image is now required. Return true
- // if it was found in the ResourceCache and doesn't need to be regenerated.
- // If false is returned the caller should (re)render the layer into the
- // newly acquired texture.
- bool lock(GrCachedLayer* layer, const GrTextureDesc& desc);
+
+ // Inform the cache that layer's cached image is now required.
+ // Return true if the layer must be re-rendered. Return false if the
+ // layer was found in the cache and can be reused.
+ bool lock(GrCachedLayer* layer, const GrTextureDesc& desc, bool dontAtlas);
// Inform the cache that layer's cached image is not currently required
void unlock(GrCachedLayer* layer);
@@ -228,7 +227,10 @@ private:
int fPlotLocks[kNumPlotsX * kNumPlotsY];
void initAtlas();
- GrCachedLayer* createLayer(const SkPicture* picture, int start, int stop, const SkMatrix& ctm);
+ GrCachedLayer* createLayer(uint32_t pictureID, int start, int stop, const SkMatrix& ctm);
+
+public:
+ void purgeAll();
// Remove all the layers (and unlock any resources) associated with 'pictureID'
void purge(uint32_t pictureID);
@@ -237,6 +239,8 @@ private:
return width <= kPlotWidth && height <= kPlotHeight;
}
+ void purgePlot(GrPlot* plot);
+
// Try to find a purgeable plot and clear it out. Return true if a plot
// was purged; false otherwise.
bool purgePlot();
diff --git a/src/gpu/SkGpuDevice.cpp b/src/gpu/SkGpuDevice.cpp
index e459a116df..64439a1882 100644
--- a/src/gpu/SkGpuDevice.cpp
+++ b/src/gpu/SkGpuDevice.cpp
@@ -1989,7 +1989,7 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
if (pullForward[i]) {
const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
- GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture,
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayerOrCreate(picture->uniqueID(),
info.fSaveLayerOpID,
info.fRestoreOpID,
info.fCTM);
@@ -2007,7 +2007,8 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
desc.fConfig = kSkia8888_GrPixelConfig;
// TODO: need to deal with sample count
- bool needsRendering = !fContext->getLayerCache()->lock(layer, desc);
+ bool needsRendering = fContext->getLayerCache()->lock(layer, desc,
+ info.fHasNestedLayers || info.fIsNested);
if (NULL == layer->texture()) {
continue;
}
@@ -2126,13 +2127,22 @@ bool SkGpuDevice::EXPERIMENTAL_drawPicture(SkCanvas* mainCanvas, const SkPicture
for (int i = 0; i < gpuData->numSaveLayers(); ++i) {
const GPUAccelData::SaveLayerInfo& info = gpuData->saveLayerInfo(i);
- GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture,
+ GrCachedLayer* layer = fContext->getLayerCache()->findLayer(picture->uniqueID(),
info.fSaveLayerOpID,
info.fRestoreOpID,
info.fCTM);
fContext->getLayerCache()->unlock(layer);
}
+#if DISABLE_CACHING
+ // This code completely clears out the atlas. It is required when
+ // caching is disabled so the atlas doesn't fill up and force more
+ // free floating layers
+ fContext->getLayerCache()->purge(picture->uniqueID());
+
+ fContext->getLayerCache()->purgeAll();
+#endif
+
return true;
}
diff --git a/tests/GpuLayerCacheTest.cpp b/tests/GpuLayerCacheTest.cpp
index 789854cf1f..5e18197ed7 100644
--- a/tests/GpuLayerCacheTest.cpp
+++ b/tests/GpuLayerCacheTest.cpp
@@ -31,11 +31,11 @@ static void create_layers(skiatest::Reporter* reporter,
int idOffset) {
for (int i = 0; i < numToAdd; ++i) {
- GrCachedLayer* layer = cache->findLayerOrCreate(&picture,
+ GrCachedLayer* layer = cache->findLayerOrCreate(picture.uniqueID(),
idOffset+i+1, idOffset+i+2,
SkMatrix::I());
REPORTER_ASSERT(reporter, NULL != layer);
- GrCachedLayer* temp = cache->findLayer(&picture, idOffset+i+1, idOffset+i+2, SkMatrix::I());
+ GrCachedLayer* temp = cache->findLayer(picture.uniqueID(), idOffset+i+1, idOffset+i+2, SkMatrix::I());
REPORTER_ASSERT(reporter, temp == layer);
REPORTER_ASSERT(reporter, TestingAccess::NumLayers(cache) == idOffset + i + 1);
@@ -60,11 +60,11 @@ static void lock_layer(skiatest::Reporter* reporter,
desc.fHeight = 512;
desc.fConfig = kSkia8888_GrPixelConfig;
- bool foundInCache = cache->lock(layer, desc);
- REPORTER_ASSERT(reporter, !foundInCache);
+ bool needsRerendering = cache->lock(layer, desc, false);
+ REPORTER_ASSERT(reporter, needsRerendering);
- foundInCache = cache->lock(layer, desc);
- REPORTER_ASSERT(reporter, foundInCache);
+ needsRerendering = cache->lock(layer, desc, false);
+ REPORTER_ASSERT(reporter, !needsRerendering);
REPORTER_ASSERT(reporter, NULL != layer->texture());
REPORTER_ASSERT(reporter, layer->locked());
@@ -99,7 +99,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) {
create_layers(reporter, &cache, *picture, kInitialNumLayers, 0);
for (int i = 0; i < kInitialNumLayers; ++i) {
- GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I());
+ GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I());
REPORTER_ASSERT(reporter, NULL != layer);
lock_layer(reporter, &cache, layer);
@@ -116,14 +116,14 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) {
// Unlock the textures
for (int i = 0; i < kInitialNumLayers; ++i) {
- GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I());
+ GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I());
REPORTER_ASSERT(reporter, NULL != layer);
cache.unlock(layer);
}
for (int i = 0; i < kInitialNumLayers; ++i) {
- GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I());
+ GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I());
REPORTER_ASSERT(reporter, NULL != layer);
REPORTER_ASSERT(reporter, !layer->locked());
@@ -142,7 +142,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) {
// Add an additional layer. Since all the layers are unlocked this
// will force out the first atlased layer
create_layers(reporter, &cache, *picture, 1, kInitialNumLayers);
- GrCachedLayer* layer = cache.findLayer(picture,
+ GrCachedLayer* layer = cache.findLayer(picture->uniqueID(),
kInitialNumLayers+1, kInitialNumLayers+2,
SkMatrix::I());
REPORTER_ASSERT(reporter, NULL != layer);
@@ -152,7 +152,7 @@ DEF_GPUTEST(GpuLayerCache, reporter, factory) {
}
for (int i = 0; i < kInitialNumLayers+1; ++i) {
- GrCachedLayer* layer = cache.findLayer(picture, i+1, i+2, SkMatrix::I());
+ GrCachedLayer* layer = cache.findLayer(picture->uniqueID(), i+1, i+2, SkMatrix::I());
// 3 old layers plus the new one should be in the atlas.
if (1 == i || 2 == i || 3 == i || 5 == i) {
REPORTER_ASSERT(reporter, NULL != layer);