aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Derek Sollenberger <djsollen@google.com>2018-03-29 13:40:02 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-29 18:08:15 +0000
commitcf6da8c0f29877249a55949efd8b952b5b9bc01d (patch)
tree9f4bcd3033dd85d378da916e7f45ab583524c595
parent9c6f6a52764281f6c61c2daf21f4737df5df53c7 (diff)
Dump additional details about the gpu resources.
GpuResources now dump optional string values that describe the type and category of the resource. The type provides a description of the kind of resource it is (e.g. texture, buffer object, stencil, etc.) and the category describes what the resource is currently tasked to do (e.g. path masks, images, scratch, etc.) This CL also refactors the dump logic in an attempt to consolidate duplicated code into GrGpuResources.cpp. Bug: b/74435803 Change-Id: I83cae825f41e6450a21398ab3ecea349c7c61c15 Reviewed-on: https://skia-review.googlesource.com/115989 Commit-Queue: Derek Sollenberger <djsollen@google.com> Reviewed-by: Robert Phillips <robertphillips@google.com>
-rw-r--r--bench/GrResourceCacheBench.cpp1
-rw-r--r--include/core/SkTraceMemoryDump.h4
-rw-r--r--include/gpu/GrGpuResource.h26
-rw-r--r--include/gpu/GrResourceKey.h12
-rw-r--r--include/gpu/GrSurface.h2
-rw-r--r--src/gpu/GrBuffer.h1
-rw-r--r--src/gpu/GrGpuResource.cpp31
-rw-r--r--src/gpu/GrPath.cpp2
-rw-r--r--src/gpu/GrPath.h1
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp6
-rw-r--r--src/gpu/GrStencilAttachment.h1
-rw-r--r--src/gpu/SkGr.cpp2
-rw-r--r--src/gpu/effects/GrCircleBlurFragmentProcessor.cpp2
-rw-r--r--src/gpu/effects/GrRRectBlurEffect.h2
-rw-r--r--src/gpu/effects/GrRectBlurEffect.h2
-rw-r--r--src/gpu/gl/GrGLRenderTarget.cpp13
-rw-r--r--src/gpu/gl/GrGLTexture.cpp15
-rw-r--r--src/gpu/gl/GrGLTextureRenderTarget.cpp7
-rw-r--r--src/gpu/ops/GrTessellatingPathRenderer.cpp2
-rw-r--r--tests/ResourceCacheTest.cpp8
20 files changed, 94 insertions, 46 deletions
diff --git a/bench/GrResourceCacheBench.cpp b/bench/GrResourceCacheBench.cpp
index a530e628e8..cc185cf04f 100644
--- a/bench/GrResourceCacheBench.cpp
+++ b/bench/GrResourceCacheBench.cpp
@@ -38,6 +38,7 @@ public:
private:
size_t onGpuMemorySize() const override { return 100; }
+ const char* getResourceType() const override { return "bench"; }
typedef GrGpuResource INHERITED;
};
diff --git a/include/core/SkTraceMemoryDump.h b/include/core/SkTraceMemoryDump.h
index 03656b2c37..e9cb5b20e4 100644
--- a/include/core/SkTraceMemoryDump.h
+++ b/include/core/SkTraceMemoryDump.h
@@ -50,6 +50,10 @@ public:
const char* units,
uint64_t value) = 0;
+ virtual void dumpStringValue(const char* /*dumpName*/,
+ const char* /*valueName*/,
+ const char* /*value*/) { }
+
/**
* Sets the memory backing for an existing dump.
* backingType and backingObjectId are used by the embedder to associate the memory dumped via
diff --git a/include/gpu/GrGpuResource.h b/include/gpu/GrGpuResource.h
index 70c94c0e55..2da8085908 100644
--- a/include/gpu/GrGpuResource.h
+++ b/include/gpu/GrGpuResource.h
@@ -249,6 +249,15 @@ public:
**/
virtual void dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const;
+ /**
+ * Describes the type of gpu resource that is represented by the implementing
+ * class (e.g. texture, buffer object, stencil). This data is used for diagnostic
+ * purposes by dumpMemoryStatistics().
+ *
+ * The value returned is expected to be long lived and will not be copied by the caller.
+ */
+ virtual const char* getResourceType() const = 0;
+
static uint32_t CreateUniqueID();
protected:
@@ -280,11 +289,24 @@ protected:
void didChangeGpuMemorySize() const;
/**
- * Allows subclasses to add additional backing information to the SkTraceMemoryDump. Called by
- * onMemoryDump. The default implementation adds no backing information.
+ * Allows subclasses to add additional backing information to the SkTraceMemoryDump.
**/
virtual void setMemoryBacking(SkTraceMemoryDump*, const SkString&) const {}
+ /**
+ * Returns a string that uniquely identifies this resource.
+ */
+ SkString getResourceName() const;
+
+ /**
+ * A helper for subclasses that override dumpMemoryStatistics(). This method using a format
+ * consistent with the default implementation of dumpMemoryStatistics() but allows the caller
+ * to customize various inputs.
+ */
+ void dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump, const SkString& resourceName,
+ const char* type, size_t size) const;
+
+
private:
/**
* Called by the registerWithCache if the resource is available to be used as scratch.
diff --git a/include/gpu/GrResourceKey.h b/include/gpu/GrResourceKey.h
index c0a08f8add..ef319ad1fa 100644
--- a/include/gpu/GrResourceKey.h
+++ b/include/gpu/GrResourceKey.h
@@ -241,7 +241,7 @@ public:
GrUniqueKey& operator=(const GrUniqueKey& that) {
this->INHERITED::operator=(that);
this->setCustomData(sk_ref_sp(that.getCustomData()));
- SkDEBUGCODE(fTag = that.fTag;)
+ fTag = that.fTag;
return *this;
}
@@ -257,14 +257,13 @@ public:
return fData.get();
}
- SkDEBUGCODE(const char* tag() const { return fTag.c_str(); })
+ const char* tag() const { return fTag; }
class Builder : public INHERITED::Builder {
public:
Builder(GrUniqueKey* key, Domain type, int data32Count, const char* tag = nullptr)
: INHERITED::Builder(key, type, data32Count) {
- SkDEBUGCODE(key->fTag = tag;)
- (void) tag; // suppress unused named param warning.
+ key->fTag = tag;
}
/** Used to build a key that wraps another key and adds additional data. */
@@ -277,8 +276,7 @@ public:
const uint32_t* srcData = innerKey.data();
(*innerKeyData++) = innerKey.domain();
memcpy(innerKeyData, srcData, innerKey.dataSize());
- SkDEBUGCODE(key->fTag = tag;)
- (void) tag; // suppress unused named param warning.
+ key->fTag = tag;
}
private:
@@ -290,7 +288,7 @@ public:
private:
sk_sp<SkData> fData;
- SkDEBUGCODE(SkString fTag;)
+ const char* fTag;
};
/**
diff --git a/include/gpu/GrSurface.h b/include/gpu/GrSurface.h
index 5fc365b562..46d3945de4 100644
--- a/include/gpu/GrSurface.h
+++ b/include/gpu/GrSurface.h
@@ -114,6 +114,8 @@ protected:
void onAbandon() override;
private:
+ const char* getResourceType() const override { return "Surface"; }
+
GrPixelConfig fConfig;
int fWidth;
int fHeight;
diff --git a/src/gpu/GrBuffer.h b/src/gpu/GrBuffer.h
index b2201a140f..33a7f354fa 100644
--- a/src/gpu/GrBuffer.h
+++ b/src/gpu/GrBuffer.h
@@ -123,6 +123,7 @@ private:
virtual bool onUpdateData(const void* src, size_t srcSizeInBytes);
size_t onGpuMemorySize() const override { return fSizeInBytes; } // TODO: zero for cpu backed?
+ const char* getResourceType() const override { return "Buffer Object"; }
void computeScratchKey(GrScratchKey* key) const override;
size_t fSizeInBytes;
diff --git a/src/gpu/GrGpuResource.cpp b/src/gpu/GrGpuResource.cpp
index d90498d6f4..ec7113562b 100644
--- a/src/gpu/GrGpuResource.cpp
+++ b/src/gpu/GrGpuResource.cpp
@@ -73,20 +73,33 @@ void GrGpuResource::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) con
return;
}
- // Dump resource as "skia/gpu_resources/resource_#".
- SkString dumpName("skia/gpu_resources/resource_");
- dumpName.appendU32(this->uniqueID().asUInt());
+ this->dumpMemoryStatisticsPriv(traceMemoryDump, this->getResourceName(),
+ this->getResourceType(), this->gpuMemorySize());
+}
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", this->gpuMemorySize());
+void GrGpuResource::dumpMemoryStatisticsPriv(SkTraceMemoryDump* traceMemoryDump,
+ const SkString& resourceName,
+ const char* type, size_t size) const {
+ const char* tag = "Scratch";
+ if (fUniqueKey.isValid()) {
+ tag = (fUniqueKey.tag() != nullptr) ? fUniqueKey.tag() : "Other";
+ }
+ traceMemoryDump->dumpNumericValue(resourceName.c_str(), "size", "bytes", size);
+ traceMemoryDump->dumpStringValue(resourceName.c_str(), "type", type);
+ traceMemoryDump->dumpStringValue(resourceName.c_str(), "category", tag);
if (this->isPurgeable()) {
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes",
- this->gpuMemorySize());
+ traceMemoryDump->dumpNumericValue(resourceName.c_str(), "purgeable_size", "bytes", size);
}
- // Call setMemoryBacking to allow sub-classes with implementation specific backings (such as GL
- // objects) to provide additional information.
- this->setMemoryBacking(traceMemoryDump, dumpName);
+ this->setMemoryBacking(traceMemoryDump, resourceName);
+}
+
+SkString GrGpuResource::getResourceName() const {
+ // Dump resource as "skia/gpu_resources/resource_#".
+ SkString resourceName("skia/gpu_resources/resource_");
+ resourceName.appendU32(this->uniqueID().asUInt());
+ return resourceName;
}
const GrContext* GrGpuResource::getContext() const {
diff --git a/src/gpu/GrPath.cpp b/src/gpu/GrPath.cpp
index 836cc5ed55..c0c56430a6 100644
--- a/src/gpu/GrPath.cpp
+++ b/src/gpu/GrPath.cpp
@@ -25,7 +25,7 @@ void GrPath::ComputeKey(const GrShape& shape, GrUniqueKey* key, bool* outIsVolat
return;
}
static const GrUniqueKey::Domain kGeneralPathDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(key, kGeneralPathDomain, geoCnt + styleCnt);
+ GrUniqueKey::Builder builder(key, kGeneralPathDomain, geoCnt + styleCnt, "Path");
shape.writeUnstyledKey(&builder[0]);
if (styleCnt) {
write_style_key(&builder[geoCnt], shape.style());
diff --git a/src/gpu/GrPath.h b/src/gpu/GrPath.h
index 19538370d5..cf4a11d4fd 100644
--- a/src/gpu/GrPath.h
+++ b/src/gpu/GrPath.h
@@ -51,6 +51,7 @@ protected:
#endif
private:
+ const char* getResourceType() const override { return "Path Data"; }
typedef GrGpuResource INHERITED;
};
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index 228625f4fb..15ea55d4f2 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -290,14 +290,16 @@ bool GrSoftwarePathRenderer::onDrawPath(const DrawPathArgs& args) {
// Fractional translate does not affect caching on Android. This is done for better cache
// hit ratio and speed, but it is matching HWUI behavior, which doesn't consider the matrix
// at all when caching paths.
- GrUniqueKey::Builder builder(&maskKey, kDomain, 4 + args.fShape->unstyledKeySize());
+ GrUniqueKey::Builder builder(&maskKey, kDomain, 4 + args.fShape->unstyledKeySize(),
+ "SW Path Mask");
#else
SkScalar tx = args.fViewMatrix->get(SkMatrix::kMTransX);
SkScalar ty = args.fViewMatrix->get(SkMatrix::kMTransY);
// Allow 8 bits each in x and y of subpixel positioning.
SkFixed fracX = SkScalarToFixed(SkScalarFraction(tx)) & 0x0000FF00;
SkFixed fracY = SkScalarToFixed(SkScalarFraction(ty)) & 0x0000FF00;
- GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyledKeySize());
+ GrUniqueKey::Builder builder(&maskKey, kDomain, 5 + args.fShape->unstyledKeySize(),
+ "SW Path Mask");
#endif
builder[0] = SkFloat2Bits(sx);
builder[1] = SkFloat2Bits(sy);
diff --git a/src/gpu/GrStencilAttachment.h b/src/gpu/GrStencilAttachment.h
index df5677d163..e8c56cca4d 100644
--- a/src/gpu/GrStencilAttachment.h
+++ b/src/gpu/GrStencilAttachment.h
@@ -45,6 +45,7 @@ protected:
}
private:
+ const char* getResourceType() const override { return "Stencil"; }
int fWidth;
int fHeight;
diff --git a/src/gpu/SkGr.cpp b/src/gpu/SkGr.cpp
index ec06561efc..b4cb22bd10 100644
--- a/src/gpu/SkGr.cpp
+++ b/src/gpu/SkGr.cpp
@@ -57,7 +57,7 @@ void GrMakeKeyFromImageID(GrUniqueKey* key, uint32_t imageID, const SkIRect& ima
SkASSERT(imageID);
SkASSERT(!imageBounds.isEmpty());
static const GrUniqueKey::Domain kImageIDDomain = GrUniqueKey::GenerateDomain();
- GrUniqueKey::Builder builder(key, kImageIDDomain, 5);
+ GrUniqueKey::Builder builder(key, kImageIDDomain, 5, "Image");
builder[0] = imageID;
builder[1] = imageBounds.fLeft;
builder[2] = imageBounds.fTop;
diff --git a/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp b/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
index d44f431dd3..618da34fcc 100644
--- a/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
+++ b/src/gpu/effects/GrCircleBlurFragmentProcessor.cpp
@@ -200,7 +200,7 @@ static sk_sp<GrTextureProxy> create_profile_texture(GrProxyProvider* proxyProvid
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
- GrUniqueKey::Builder builder(&key, kDomain, 1);
+ GrUniqueKey::Builder builder(&key, kDomain, 1, "1-D Circular Blur");
builder[0] = sigmaToCircleRRatioFixed;
builder.finish();
diff --git a/src/gpu/effects/GrRRectBlurEffect.h b/src/gpu/effects/GrRRectBlurEffect.h
index 1d382a0dfa..b59d1be7d6 100644
--- a/src/gpu/effects/GrRRectBlurEffect.h
+++ b/src/gpu/effects/GrRRectBlurEffect.h
@@ -34,7 +34,7 @@ public:
float xformedSigma) {
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
- GrUniqueKey::Builder builder(&key, kDomain, 9);
+ GrUniqueKey::Builder builder(&key, kDomain, 9, "RoundRect Blur Mask");
builder[0] = SkScalarCeilToInt(xformedSigma - 1 / 6.0f);
int index = 1;
diff --git a/src/gpu/effects/GrRectBlurEffect.h b/src/gpu/effects/GrRectBlurEffect.h
index 123c91fba8..e6d777980f 100644
--- a/src/gpu/effects/GrRectBlurEffect.h
+++ b/src/gpu/effects/GrRectBlurEffect.h
@@ -25,7 +25,7 @@ public:
static const GrUniqueKey::Domain kDomain = GrUniqueKey::GenerateDomain();
GrUniqueKey key;
- GrUniqueKey::Builder builder(&key, kDomain, 1);
+ GrUniqueKey::Builder builder(&key, kDomain, 1, "Rect Blur Mask");
builder[0] = profileSize;
builder.finish();
diff --git a/src/gpu/gl/GrGLRenderTarget.cpp b/src/gpu/gl/GrGLRenderTarget.cpp
index 9500e7d6fe..5513e8aaa7 100644
--- a/src/gpu/gl/GrGLRenderTarget.cpp
+++ b/src/gpu/gl/GrGLRenderTarget.cpp
@@ -216,19 +216,14 @@ void GrGLRenderTarget::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump)
// Due to this resource having both a texture and a renderbuffer component, dump as
// skia/gpu_resources/resource_#/renderbuffer
- SkString dumpName("skia/gpu_resources/resource_");
- dumpName.appendU32(this->uniqueID().asUInt());
- dumpName.append("/renderbuffer");
+ SkString resourceName = this->getResourceName();
+ resourceName.append("/renderbuffer");
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size);
-
- if (this->isPurgeable()) {
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", size);
- }
+ this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget", size);
SkString renderbuffer_id;
renderbuffer_id.appendU32(fMSColorRenderbufferID);
- traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_renderbuffer",
+ traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_renderbuffer",
renderbuffer_id.c_str());
}
}
diff --git a/src/gpu/gl/GrGLTexture.cpp b/src/gpu/gl/GrGLTexture.cpp
index 61bce35061..69b214de27 100644
--- a/src/gpu/gl/GrGLTexture.cpp
+++ b/src/gpu/gl/GrGLTexture.cpp
@@ -138,21 +138,16 @@ void GrGLTexture::dumpMemoryStatistics(SkTraceMemoryDump* traceMemoryDump) const
// Dump as skia/gpu_resources/resource_#/texture, to avoid conflicts in the
// GrGLTextureRenderTarget case, where multiple things may dump to the same resource. This
// has no downside in the normal case.
- SkString dumpName("skia/gpu_resources/resource_");
- dumpName.appendU32(this->uniqueID().asUInt());
- dumpName.append("/texture");
+ SkString resourceName = this->getResourceName();
+ resourceName.append("/texture");
// As we are only dumping our texture memory (not any additional memory tracked by classes
// which may inherit from us), specifically call GrGLTexture::gpuMemorySize to avoid
// hitting an override.
- size_t size = GrGLTexture::gpuMemorySize();
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "size", "bytes", size);
-
- if (this->isPurgeable()) {
- traceMemoryDump->dumpNumericValue(dumpName.c_str(), "purgeable_size", "bytes", size);
- }
+ this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "Texture",
+ GrGLTexture::gpuMemorySize());
SkString texture_id;
texture_id.appendU32(this->textureID());
- traceMemoryDump->setMemoryBacking(dumpName.c_str(), "gl_texture", texture_id.c_str());
+ traceMemoryDump->setMemoryBacking(resourceName.c_str(), "gl_texture", texture_id.c_str());
}
diff --git a/src/gpu/gl/GrGLTextureRenderTarget.cpp b/src/gpu/gl/GrGLTextureRenderTarget.cpp
index e9f224b71b..049cb31a9b 100644
--- a/src/gpu/gl/GrGLTextureRenderTarget.cpp
+++ b/src/gpu/gl/GrGLTextureRenderTarget.cpp
@@ -37,9 +37,16 @@ GrGLTextureRenderTarget::GrGLTextureRenderTarget(GrGLGpu* gpu,
void GrGLTextureRenderTarget::dumpMemoryStatistics(
SkTraceMemoryDump* traceMemoryDump) const {
+#ifndef SK_BUILD_FOR_ANDROID_FRAMEWORK
// Delegate to the base classes
GrGLRenderTarget::dumpMemoryStatistics(traceMemoryDump);
GrGLTexture::dumpMemoryStatistics(traceMemoryDump);
+#else
+ SkString resourceName = this->getResourceName();
+ resourceName.append("/texture_renderbuffer");
+ this->dumpMemoryStatisticsPriv(traceMemoryDump, resourceName, "RenderTarget",
+ this->gpuMemorySize());
+#endif
}
bool GrGLTextureRenderTarget::canAttemptStencilAttachment() const {
diff --git a/src/gpu/ops/GrTessellatingPathRenderer.cpp b/src/gpu/ops/GrTessellatingPathRenderer.cpp
index 8eaadf0ac3..651d34fae7 100644
--- a/src/gpu/ops/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/ops/GrTessellatingPathRenderer.cpp
@@ -245,7 +245,7 @@ private:
static constexpr int kClipBoundsCnt = sizeof(fDevClipBounds) / sizeof(uint32_t);
int shapeKeyDataCnt = fShape.unstyledKeySize();
SkASSERT(shapeKeyDataCnt >= 0);
- GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt);
+ GrUniqueKey::Builder builder(&key, kDomain, shapeKeyDataCnt + kClipBoundsCnt, "Path");
fShape.writeUnstyledKey(&builder[0]);
// For inverse fills, the tessellation is dependent on clip bounds.
if (inverseFill) {
diff --git a/tests/ResourceCacheTest.cpp b/tests/ResourceCacheTest.cpp
index c56bd01564..11dcdd43b6 100644
--- a/tests/ResourceCacheTest.cpp
+++ b/tests/ResourceCacheTest.cpp
@@ -340,6 +340,7 @@ private:
}
size_t onGpuMemorySize() const override { return fSize; }
+ const char* getResourceType() const override { return "Test"; }
TestResource* fToDelete;
size_t fSize;
@@ -1661,19 +1662,24 @@ static void test_tags(skiatest::Reporter* reporter) {
GrResourceCache* cache = mock.cache();
GrGpu* gpu = context->contextPriv().getGpu();
+ // tag strings are expected to be long lived
+ std::vector<SkString> tagStrings;
+
SkString tagStr;
int tagIdx = 0;
int currTagCnt = 0;
for (int i = 0; i < kNumResources; ++i, ++currTagCnt) {
+
sk_sp<GrGpuResource> resource(new TestResource(gpu));
GrUniqueKey key;
if (currTagCnt == tagIdx) {
tagIdx += 1;
currTagCnt = 0;
tagStr.printf("tag%d", tagIdx);
+ tagStrings.emplace_back(tagStr);
}
- make_unique_key<1>(&key, i, tagStr.c_str());
+ make_unique_key<1>(&key, i, tagStrings.back().c_str());
resource->resourcePriv().setUniqueKey(key);
}
SkASSERT(kLastTagIdx == tagIdx);